Skip to the content.

関数

複数の戻り値

名前付き結果パラメータ

Defer

Lập lịch gọi 1 hàm thực hiện ngay trước khi return. Một hàm đặc biệt nhưng hiệu quả trong tình huống phải release 1 resource bất kỳ khi nào hàm bị return. Ví dụ kinh điển là unlocking a mutex hoặc đóng file.

// Contents returns the file's contents as a string.
func Contents(filename string) (string, error) {
    f, err := os.Open(filename)
    if err != nil {
        return "", err
    }
    defer f.Close()  // f.Close will run when we're finished.

    var result []byte
    buf := make([]byte, 100)
    for {
        n, err := f.Read(buf[0:])
        result = append(result, buf[0:n]...) // append is discussed later.
        if err != nil {
            if err == io.EOF {
                break
            }
            return "", err  // f will be closed if we return here.
        }
    }
    return string(result), nil // f will be closed if we return here.
}

Lợi ích:

Giá trị biến đầu vào của defer function được ấn định khi hàm defer thực thi, không phải lúc hàm gọi được thực thi

for i := 0; i < 5; i++ {
    defer fmt.Printf("%d ", i)
}

Các hàm đã defer được thực thi theo LIFO. -> Đoạn code trên sẽ in ra 4 3 2 1 0 khi hàm return

newでメモリを割り当て

new(T)につき、Go の用語では、新しく割り当てられた T 型のゼロ値へのポインタを返します。

Constructors and composite literals

Constructors

func NewFile(fd int, name string) *File {
    if fd < 0 {
        return nil
    }
    f := new(File)
    f.fd = fd
    f.name = name
    f.dirinfo = nil
    f.nepipe = 0
    return f
}

composite literal

func NewFile(fd int, name string) *File {
    if fd < 0 {
        return nil
    }
    f = File{fd, name, nil, 0}
    return &f
}

makeでメモリを割り当て

slices, map, chanelのみを作成し、タイプ T (*T ではない) の初期化された (ゼロ化されていない) 値を返します。

var p *[]int = new([]int)       // allocates slice structure; *p == nil; rarely useful
var v  []int = make([]int, 100) // the slice v now refers to a new array of 100 ints

// Unnecessarily complex:
var p *[]int = new([]int)
*p = make([]int, 100, 100)

// Idiomatic:
v := make([]int, 100)

Arrays

array := […]float64{7.0, 8.5, 9.1} x := Sum(&array) // Note the explicit address-of operator

But even this style isn't idiomatic Go. Use slices instead.
## Slices
- Slices hold references to an underlying array, and if you assign one slice to another, both refer to the same array. 
- If a function takes a slice argument, changes it makes to the elements of the slice will be visible to the caller, analogous to passing a pointer to the underlying array

### Append関数
```go
func Append(slice, data []byte) []byte {
    l := len(slice)
    if l + len(data) > cap(slice) {  // reallocate
        // Allocate double what's needed, for future growth.
        newSlice := make([]byte, (l+len(data))*2)
        // The copy function is predeclared and works for any slice type.
        copy(newSlice, slice)
        slice = newSlice
    }
    slice = slice[0:l+len(data)]
    copy(slice[l:], data)
    return slice
}

Maps

Key Value struct

Key type: equality operator is defined such as integers, floating point and complex numbers, strings, pointers, interfaces (as long as the dynamic type supports equality), structs and arrays. Slices cannot be used as map keys, because equality is not defined on them

var timeZone = map[string]int{
    "UTC":  0*60*60,
    "EST": -5*60*60,
    "CST": -6*60*60,
    "MST": -7*60*60,
    "PST": -8*60*60,
}
offset := timeZone["EST"]

Need to distinguish a missing entry from a zero value

var seconds int
var ok bool
seconds, ok = timeZone[tz]

func offset(tz string) int {
    if seconds, ok := timeZone[tz]; ok {
        return seconds
    }
    log.Println("unknown time zone:", tz)
    return 0
}

To delete a map entry, use the delete built-in function, whose arguments are the map and the key to be deleted. It’s safe to do this even if the key is already absent from the map.

delete(timeZone, "PDT")  // Now on Standard Time

Constants