GOLANG_TIPS

// 能夠兩個結果也可一個結果,實現?
v, ok = m[key] // map lookup
v, ok = x.(T) // type assertion
v, ok = <-ch // channel receive

v = m[key] // map查找,失敗時返回零值
v = x.(T) // type斷言,失敗時panic異常
v = <-ch // 管道接收,失敗時返回零值(阻塞不算是失敗)
複製代碼
out := strings[:0] //共享底層數組建立空切片

in := bufio.NewReader(os.Stdin) // io
複製代碼

一個命名爲S的結構體類型將不能再包含S類型的成員:由於一個聚合的值不能包含它自身。 (該限制一樣適應於數組。)可是S類型的結構體能夠包含 *S 指針類型的成員json

寫做struct{}。它的大小爲0 好比用來作控制而非數據信息: chan struct{} 好比用來實現set: map[string]struct{} 若是結構體的所有成員都是能夠比較的,那麼結構體也是能夠比較的,可比較的結構體類型和其餘可比較的類型同樣,能夠用於map的key類型。 須要注意的是Printf函數中%v參數包含的#副詞,它表示用和Go語言相似的語法打印值。對於 結構體類型來講,將包含每一個成員的名字。數組

data, err := json.MarshalIndent(movies, "", " ")
複製代碼
func add(x int, y int) int {return x + y}
func sub(x, y int) (z int) { z = x - y; return}
func first(x int, _ int) int { return x }
func zero(int, int) int { return 0 }

複製代碼

你可能會偶爾遇到沒有函數體的函數聲明,這表示該函數不是以Go實現的。這樣的聲明定義 了函數標識符。函數

package math func Sin(x float64) float //implemented in assembly language 複製代碼

可是函數值之間是不可比較的,也不能用函數值做爲map的key。工具

func bigSlowOperation() {
    defer trace("bigSlowOperation")() // don't forget the
    extra parentheses
    // ...lots of work…
    time.Sleep(10 * time.Second) // simulate slow
    operation by sleeping
}
func trace(msg string) func() {
    start := time.Now()
    log.Printf("enter %s", msg)
    return func() {
        log.Printf("exit %s (%s)", msg,time.Since(start))
    }
}
複製代碼
func double(x int) (result int) {
    defer func() { fmt.Printf("double(%d) = %d\n", x,result) }()
    return x + x
}
_ = double(4)
// Output:
// "double(4) = 8"

func triple(x int) (result int) {
    defer func() { result += x }()
    return double(x)
}
fmt.Println(triple(4)) // "12"
複製代碼
  • 當panic異常發生時,程序會中斷運行,並當即執行在該goroutine(能夠先理解成 線程,在第8章會詳細介紹)中被延遲的函數(defer 機制)。
type P *int
func (P) f() { /* ... */ } // compile error: invalid receiver type
複製代碼
m = nil
fmt.Println(m.Get("item")) // ""
m.Add("item", "3") // panic: assignment to entry in nil map
複製代碼

,內嵌字段會指導編譯器去生成額外的包裝方法來委託已經聲明好的方法:(而不是cat is a animal,是cat has a animal) 內嵌字段,屬性方法同層不能存在同一命名的ui

type Point struct{ X, Y float64 }
func (p Point) Add(q Point) Point { return Point{p.X + q.X, p.Y + q.Y} }
func (p Point) Sub(q Point) Point { return Point{p.X - q.X, p.Y - q.Y} }
type Path []Point
func (path Path) TranslateBy(offset Point, add bool) {
    var op func(p, q Point) Point if add {
        op = Point.Add
    } else {
        op = Point.Sub
    }
    for i := range path {
        // Call either path[i].Add(offset) or path[i].Sub(offset).
        path[i] = op(path[i], offset)
}
複製代碼

對於接口,必須是該對象實現了方法,對象的指針實現了沒有用url

package flag
// Value is the interface to the value stored in a flag.
type Value interface {
    String() string
    Set(string) error
}
複製代碼
var w io.Writer
w = os.Stdout
w = new(bytes.Buffer)
w = nil
複製代碼

->
->
->

非指針時value包含這個對象 注意接口爲nil和接口的value值爲nil是兩個概念spa

接口是能夠比較的線程

var w io.Writer
fmt.Printf("%T\n", w) // "<nil>"
w = os.Stdout
fmt.Printf("%T\n", w) // "*os.File"
w = new(bytes.Buffer)
fmt.Printf("%T\n", w) // "*bytes.Buffer"

複製代碼

若是斷言操做的對象是一個nil接口值,那麼不論被斷言的類型是什麼這個類型斷言都會失 敗指針

switch x.(type) {
    case nil: // ...
    case int, uint: // ...
    case bool: // ...
    case string: // ...
    default: // ...
}
複製代碼
  • Channel還支持close操做,用於關閉channel,隨後對基於該channel的任何發送操做都將導 致panic異常。對一個已經被close過的channel之行接收操做依然能夠接受到以前已經成功發 送的數據;若是channel中已經沒有數據的話講產生一個零值的數據
  • 當一個被關閉的channel中已經發送的數據都被成功接收後,後續的接收操做將再也不阻塞,它們會當即返回一個零值(能夠用這個特性,建立一個chan,<-chan 直到close(chan))
package main
import "fmt"

func counter(out chan<- int) {
	for x := 0; x < 100; x++ {
		out <- x
	}
	close(out)
}
func squarer(out chan<- int, in <-chan int) {
	for v := range in {
		out <- v * v
	}
	close(out)
}
func printer(in <-chan int) {
	for v := range in {
		fmt.Println(v)
	}
}
func main() {
	naturals := make(chan int)
	squares := make(chan int)
	go counter(naturals)
	go squarer(squares, naturals)
	printer(squares)
}
// range ch 會一直到close(ch)才結束
複製代碼

重複關閉一個channel將致使panic異常,視圖關閉一個nil值的channel也將致使panic異 常。關閉一個channels還會觸發一個廣播機制 由於關閉操做只用於斷言再也不向channel發送新的數據,因此只有在發送者所在的goroutine才 會調用close函數,所以對一個只接收的channel調用close將是一個編譯錯誤。code

var loadIconsOnce sync.Once
var icons map[string]image.Image
// Concurrency-safe.
func Icon(name string) image.Image {
loadIconsOnce.Do(loadIcons)
return icons[name]
}
> 只要在go build,go run或者go test命令後面加上-race的flag,就會使編譯器建立一個你的應
用的「修改」版或者一個附帶了可以記錄全部運行期對共享變量訪問工具的test,而且會記錄下
每個讀或者寫共享變量的goroutine的身份信息

複製代碼

Go語言的構建工具對包含internal名字的路徑段的包導入路徑作了特殊處理。這種包叫internal包,一個internal包只能被和internal目錄有同一個父目錄的包所導入。例如,net/http/internal/chunked內部包只能被net/http/httputil或net/http包導入,可是不能被net/url包導入。不過net/url包卻能夠導入net/http/httputil包

咱們能夠經過調用reflect.ValueOf(&x).Elem(),來獲取任意變量x對應的可取地址的Value

相關文章
相關標籤/搜索
本站公眾號
   歡迎關注本站公眾號,獲取更多信息