the go programming language note

2018-06-27  本文已影响0人  onbug

Chapter 1

1.2

i++ is statement, so j = i++ is illegal
s := "" can be only used within a function

Package-level variables are initialized before main begins (§2.6.2), and local variables are initialized as their declarations are encountered during function execution

Since new is a predeclared function, not a key word, it’s possible to redefine the name for something else within a function

Chapter 2

2.3

The zero value of an aggregate type like an array or a struct has the zero value of all of its elements or fields.
The zero-value me chanism ensures that a variable always holds a well-define d value of its type; in Go there is no such thing as an uninitialized variable.

Keep in mind that := is a declaration, whereas = is an assignment

A short variable declaration must declare at least one new variable, however, so this code will not compile:

    f, err := os.Open(infile)
    // ...
    f, err := os.Create(outfile) // compile error: no new variables

Each call to new returns a distinct variable with aunique address:

     p := new(int)
     q := new(int)
     fmt.Println(p == q) // "false"

There is one except ion to this rule: two variables whose type carries no infor mation and is therefore of size zero, such as struct{} or [0]int, may, depending on the implement ation, have the same address.

Chapter 3

Although Go provides unsigned numbers and arithmetic, we tend to use the signed int form even for quantities that can’t be negative, such as the length of an array, though uint might seem a more obvious choice. Indeed, the built-in len function returns a signed int, as in this loop which announces prize medals in reverse order:

     medals := []string{"gold", "silver", "bronze"}
     for i := len(medals) - 1; i >= 0; i-- {
         fmt.Println(medals[i]) // "bronze", "silver", "gold"
}

The alternative would be calamitous. If len returned an unsigned number, then i too would be a uint, and the condition i >= 0 would always be true by definition. After the third itera- tion, in which i == 0, the i-- statement would cause i to become not −1, but the maximum uint value (for example, 264−1), and the evaluation of medals[i] would fail at run time, or panic (§5.9), by attempting to access an element outside the bounds of the slice

Chapter 4

The size of an array is part of its type, so [3]int and [4]int are different types.

If an array’s element type is comparable then the array type is comparable too, so we may directly compare two arrays of that type using the == operator, which reports whether all corresponding elements are equal. The != operator is its negation.

     a := [2]int{1, 2}
     b := [...]int{1, 2}
     c := [2]int{1, 3}
     fmt.Println(a == b, a == c, b == c) // "true false false"
     d := [3]int{1, 2}
     fmt.Println(a == d) // compile error: cannot compare [2]int == [3]int

Unlike arrays, slices are not comparable, so we cannot use == to test whether two slices contain the same elements. The standard library provides the highly optimized bytes.Equal function for comparing two slices of bytes ([]byte), but for other types of slice, we must do the comparison ourselves

4.3 Maps

In Go, a map is a reference to a hash table, and a map type is written map[K]V, where K and V are the types of its keys and values. All of the keys in a given map are of the same type, and all of the values are of the same type, but the keys need not be of the same type as the values. The key type K must be comparable using ==, so that the map can test whether a given key is equal to one already within it. Though floating-point numbers are comparable, it’s a bad idea to compare floats for equality and, as we mentioned in Chapter 3, especially bad if NaN is a possible value. There are no restrictions on the value type V.

a map element is not a variable, and we cannot take its address:

     _ = &ages["bob"] // compile error: cannot take address of map element

4.4 structs

type Employee struct {
         ID        int
         Name      string
         Address   string
         DoB       time.Time
         Position  string
         Salary    int
         ManagerID int
}

Field order is significant to type identity. Had we also combined the declaration of the Position field (also a string), or interchanged Name and Address, we would be defining a different struct type.

Nor can you use the (order-based) first form of literal to sneak around the rule that unexported identifiers may not be referred to from another package.

     package p
     type T struct{ a, b int } // a and b are not exported
     package q
     import "p"
     var _ = p.T{a: 1, b: 2} // compile error: can't reference a, b
     var _ = p.T{1, 2}       // compile error: can't reference a, b

Although the last line above doesn’t mention the unexported field identifiers, it’s really using them implicitly, so it’s not allowed.

4.4.2 Comparing Structs

If all the fields of a struct are comparable, the struct itself is comparable, so two expressions of that type may be compared using == or !=.
Comparable struct types, like other comparable types, may be used as the key
type of a map.

     type address struct {
         hostname string
         port int
}
     hits := make(map[address]int)
     hits[address{"golang.org", 443}]++

Chapter 5

5.3. Multiple Return Values

func findLinks(url string) ([]string, error) {
resp, err := http.Get(url)
ˇif err != nil {
    return nil, err
}
if resp.StatusCode != http.StatusOK {
    resp.Body.Close()
    return nil, fmt.Errorf("getting %s: %s", url, resp.Status)
}
doc, err := html.Parse(resp.Body)
resp.Body.Close()
if err != nil {
    return nil, fmt.Errorf("parsing %s as HTML: %v", url, err)
}
return visit(nil, doc), nil
}

We must ensure that resp.Body is closed so that network resources are properly released even in case of error. Go’s garbage collector recycles unused memory, but do not assume it will release unused operating system resources like open files and network connections. They should be closed explicitly

Chapter 6

Named types (Point) and pointers to them (*Point) are the only types that may appear in a receiver declaration. Furthermore, to avoid ambiguities, method declarations are not permit- ted on named types that are themselves pointer types:

     type P *int
     func (P) f() { /* ... */ } // compile error: invalid receiver type

Chapter 8

func mirroredQuery() string {
         responses := make(chan string, 3)
         go func() { responses <- request("asia.gopl.io") }()
         go func() { responses <- request("europe.gopl.io") }()
         go func() { responses <- request("americas.gopl.io") }()
         return <-responses // return the quickest response
}
func request(hostname string) (response string) { /* ... */ }

Had we used an unbuffered channel, the two slower goroutines would have gotten stuck trying to send their responses on a channel from which no goroutine will ever receive. This sit- uation, called a goroutine leak, would be a bug. Unlike garbage variables, leaked goroutines are not automatically collected, so it is important to make sure that goroutines terminate them- selves when no longer needed.

Failure to allocate sufficient buffer capacity would cause the program to deadlock.

Chapter 9

It fol lows f rom t his definit ion t hat t here are t hre e ways to avoid a d at a race.
The first way is not to w r ite t he var i able
The s e cond way to avoid a d at a race is to avoid accessing t he var i able f rom mu lt iple goroutines
The t hird way to avoid a d at a race is to al low many gorout ines to access t he var i able, but on ly one at a time

上一篇下一篇

猜你喜欢

热点阅读