<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                ??碼云GVP開源項目 12k star Uniapp+ElementUI 功能強大 支持多語言、二開方便! 廣告
                1、使用指針接收方法的值的實例 只要值是可取址的,那在這個值上調用指針接收方法是沒問題的。換句話說,在某些情況下,你不需要在有一個接收值的方法版本。 然而并不是所有的變量是可取址的。Map的元素就不是。通過interface引用的變量也不是。 錯誤代碼: ~~~ package main import "fmt" type data struct { name string } func (p *data) print() { fmt.Println("name:", p.name) } type printer interface { print() } func main() { d1 := data{"one"} d1.print() //ok var in printer = data{"two"} //error in.print() m := map[string]data{"x": data{"three"}} m["x"].print() //error } ~~~ 編譯錯誤: ~~~ ./main.go:20:6: cannot use data literal (type data) as type printer in assignment: data does not implement printer (print method has pointer receiver) ./main.go:23:8: cannot call pointer method on m["x"] ./main.go:23:8: cannot take the address of m["x"] ~~~ 2、更新Map的值 如果你有一個struct值的map,你無法更新單個的struct值。 ~~~ package main type data struct { name string } func main() { m := map[string]data{"x": {"one"}} m["x"].name = "two" //error } ~~~ 編譯錯誤: ~~~ ./main.go:9:14: cannot assign to struct field m["x"].name in map ~~~ 這個操作無效是因為map元素是無法取址的。 而讓Go新手更加困惑的是slice元素是可以取址的。 ~~~ package main import "fmt" type data struct { name string } func main() { one := data{"one"} s := []data{one} s[0].name = "two" //ok fmt.Println(s) //prints: [{two}] } ~~~ 運行結果: ~~~ [{two}] ~~~ 注意在不久之前,使用編譯器之一(gccgo)是可以更新map的元素值的,但這一行為很快就被修復了 它也被認為是Go 1.3的潛在特性。在那時還不是要急需支持的,但依舊在todo list中。 第一個有效的方法是使用一個臨時變量。 ~~~ package main import "fmt" type data struct { name string } func main() { m := map[string]data{"x": {"one"}} r := m["x"] r.name = "two" m["x"] = r fmt.Printf("%v\n", m) //prints: map[x:{two}] } ~~~ 運行結果: ~~~ map[x:{two}] ~~~ 另一個有效的方法是使用指針的map。 ~~~ package main import "fmt" type data struct { name string } func main() { m := map[string]*data{"x": {"one"}} m["x"].name = "two" //ok fmt.Println(m["x"]) //prints: &{two} } ~~~ 運行結果: ~~~ &{two} ~~~ 順便說下,當你運行下面的代碼時會發生什么? ~~~ package main type data struct { name string } func main() { m := map[string]*data{"x": {"one"}} m["z"].name = "what?" //??? } ~~~ 運行錯誤: ~~~ panic: runtime error: invalid memory address or nil pointer dereference [signal SIGSEGV: segmentation violation code=0x1 addr=0x8 pc=0x104f9af] ~~~ 3、"nil" Interfaces和"nil" Interfaces的值 這在Go中是第二最常見的技巧,因為interface雖然看起來像指針,但并不是指針。interface變量僅在類型和值為“nil”時才為“nil”。 interface的類型和值會根據用于創建對應interface變量的類型和值的變化而變化。當你檢查一個interface變量是否等于“nil”時,這就會導致未預期的行為。 ~~~ package main import "fmt" func main() { var data *byte var in interface{} fmt.Println(data, data == nil) //prints: <nil> true fmt.Println(in, in == nil) //prints: <nil> true in = data fmt.Println(in, in == nil) //prints: <nil> false //'data' is 'nil', but 'in' is not 'nil' } ~~~ 運行結果: ~~~ <nil> true <nil> true <nil> false ~~~ 當你的函數返回interface時,小心這個陷阱。 ~~~ package main import "fmt" func main() { doit := func(arg int) interface{} { var result *struct{} = nil if arg > 0 { result = &struct{}{} } return result } if res := doit(-1); res != nil { fmt.Println("good result:", res) //prints: good result: <nil> //'res' is not 'nil', but its value is 'nil' } } ~~~ 運行結果: ~~~ good result: <nil> ~~~ ~~~ package main import "fmt" func main() { doit := func(arg int) interface{} { var result *struct{} = nil if arg > 0 { result = &struct{}{} } else { return nil } return result } if res := doit(-1); res != nil { fmt.Println("good result:", res) } } ~~~ 4、棧和堆變量 你并不總是知道變量是分配到棧還是堆上。在C++中,使用new創建的變量總是在堆上。在Go中,即使是使用new()或者make()函數來分配,變量的位置還是由編譯器決定。編譯器根據變量的大小和“泄露分析”的結果來決定其位置。這也意味著在局部變量上返回引用是沒問題的,而這在C或者C++這樣的語言中是不行的。 如果你想知道變量分配的位置,在“go build”或“go run”上傳入“-m“ gc標志(即,go run -gcflags -m app.go)。 5、GOMAXPROCS, 并發, 和并行 默認情況下,Go僅使用一個執行上下文/OS線程(在當前的版本)。這個數量可以通過設置GOMAXPROCS來提高。 一個常見的誤解是,GOMAXPROCS表示了CPU的數量,Go將使用這個數量來運行goroutine。而runtime.GOMAXPROCS()函數的文檔讓人更加的迷茫。GOMAXPROCS變量描述(https://golang.org/pkg/runtime/)所討論OS線程的內容比較好。 你可以設置GOMAXPROCS的數量大于CPU的數量。 ~~~ package main import ( "fmt" "runtime" ) func main() { fmt.Println(runtime.GOMAXPROCS(-1)) fmt.Println(runtime.NumCPU()) runtime.GOMAXPROCS(20) fmt.Println(runtime.GOMAXPROCS(-1)) runtime.GOMAXPROCS(300) fmt.Println(runtime.GOMAXPROCS(-1)) } ~~~ 運行結果: ~~~ 4 4 20 300 ~~~ 6、讀寫操作的重排順序 Go可能會對某些操作進行重新排序,但它能保證在一個goroutine內的所有行為順序是不變的。然而,它并不保證多goroutine的執行順序。 package main import ( "runtime" "time" ) var _ = runtime.GOMAXPROCS(3) var a, b int func u1() { a = 1 b = 2 } func u2() { a = 3 b = 4 } func p() { println(a) println(b) } func main() { go u1() go u2() go p() time.Sleep(1 * time.Second) } 如果你多運行幾次上面的代碼,你可能會發現a和b變量有多個不同的組合: a和b最有趣的組合式是"02"。這表明b在a之前更新了。 如果你需要在多goroutine內放置讀寫順序的變化,你將需要使用channel,或者使用"sync"包構建合適的結構體。 7、優先調度 有可能會出現這種情況,一個無恥的goroutine阻止其他goroutine運行。當你有一個不讓調度器運行的for循環時,這就會發生。 ~~~ package main import "fmt" func main() { done := false go func() { done = true }() for !done { } fmt.Println("done!") } ~~~ for循環并不需要是空的。只要它包含了不會觸發調度執行的代碼,就會發生這種問題。 調度器會在GC、“go”聲明、阻塞channel操作、阻塞系統調用和lock操作后運行。它也會在非內聯函數調用后執行。 ~~~ package main import "fmt" func main() { done := false go func() { done = true }() for !done { fmt.Println("not done!") //not inlined } fmt.Println("done!") } ~~~ 要想知道你在for循環中調用的函數是否是內聯的,你可以在“go build”或“go run”時傳入“-m” gc標志(如, go build -gcflags -m)。 另一個選擇是顯式的喚起調度器。你可以使用“runtime”包中的 Goshed()函數。 ~~~ package main import ( "fmt" "runtime" ) func main() { done := false go func() { done = true }() for !done { runtime.Gosched() } fmt.Println("done!") } ~~~
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看