日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

Go语言实战读书笔记

發布時間:2025/3/21 编程问答 16 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Go语言实战读书笔记 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

2019獨角獸企業重金招聘Python工程師標準>>>

Go語言實戰讀書筆記

第二章

通道(channel)、映射(map)和切片(slice)是引用類型。引用類型的對象需要使用make函數進行構造。

在Go程序中,如果函數main()返回,整個程序就終止了。這時,Go會關閉全部goroutine。

使用for range迭代切片時,每次迭代前會返回兩個值:元素在切片中的索引和元素副本。

Go支持閉包。

解析JSON示例:

type Feed struct {Name string `json:"site"`URI string `json:"link"`Type string `json:"type"` }file, _ := os.Open(filename) var feeds []*Feed json.NewDecoder(file).Decode(&feeds)

聲明接口示例:

type Matcher interface {Search(feed *Feed, searchTerm string) ([]*Result, error) }

使用指針作為接受者聲明的方法,只能由指針調用。使用值作為接受者聲明的方法,值和指針都可以調用。當使用值調用時,傳入方法的是值的副本。

如果使用for range對通道進行迭代時,當通道關閉后,迭代會終止。

除了main包外,Go包應當與其所在目錄同名。

第三章

Go在尋找包時,先從$GOROOT目錄下尋找,接著在$GOPATH目錄下尋找。

命名導入:

import myfmt "mylib/fmt" import _ "mylib/init"

包的初始化。每個包可以包含多個init函數,這些函數將在main.main()之前執行。

Go工具

構建:

go build hello.go # 構建指定文件。 go build # 構建當前目錄。 go build github.com/goinaction/code/chapter3/wordcount # 構建指定包。 go build github.com/goinaction/code/chapter3/... # 構建指定目錄下的全部包。

清理構建文件:

go clean hello.go

構建并執行:

go run hello.go

檢查代碼中的常見錯誤:

go vet go vet main.go go vet .

格式化代碼:

go fmt gofmt -l -w -s .

查看文檔:

go doc tar godoc -http=:6060

Go源代碼文檔

函數文檔示例:

// Retrieve 連接到配置庫,收集各種鏈接設置、用戶名和密碼。這個函數成功時 // 返回 config 結構,否則返回一個錯誤。 func Retrieve() (config, error) {// ... }

包文檔示例:

// 包 usb 提供了用于調用 USB 設備的類型和函數。 package usb // ...

第四章

聲明數組:

var a1 [5]int var a2 = [3]int{1, 2, 3} var a3 = [...]int{1, 2, 3} var a4 = [3]*int{0: new(int), 1: new(int)}

數組賦值會復制元素:

a1 := [3]string{"a", "b", "c"} var a2 [3]string a2 = a1

多維數組:

var a1 [4][2]int a2 := [4][2]int{{10, 11}, {20, 21}, {30, 31}, {40, 41}} a3 := [4][2]int{1: {0: 20}, 3: {1: 41}} var a4 [2]int = a3[1]

不要用數組作為函數參數。這么做會復制大量對象。要使用切片。

建立切片:

s1 := make([]int, 5) s2 := make([]int, 3, 5) s3 := []{1, 2, 3} s4 := []string{99: ""} s5 := s1[1:3] # s5和s1共享同一個底層數組 s6 := s1[2:3:4] # s6是長度為1,容量為2的切片

切片會包含一個底層數組。

切片和數組的區別在于,[]中沒有數字。

對于底層數組容量是k的切片s[i:j],其長度是j-i,容量是k-i。

在對切片進行迭代時,返回的是切片元素的副本。每次迭代時,值副本的地址是相同的。

多維切片:

s := [][]int{{10}, {100, 200}}

切片包含地址指針、長度和容量。在64位計算機上,一個切片占用24字節。復制切片時不會復制底層數組,因此將切片作為參數傳遞給函數,開銷很小。

切片函數:

cap(s) # 容量 len(s) # 長度 append(s, element)

映射使用了散列表。在每次迭代中,各元素返回的次序可能不同。

建立映射:

m1 := make(map[int]int) m2 := map[string]string{"Red": "#da1337", "Orange": "#e95a22"}

映射的鍵必須是可以使用==比較的對象。函數、切片、以及包含切片的對象,由于具有引用語義,不能作為映射的鍵。

從映射中獲取鍵對應的值時,如果鍵不存在,會返回零值。

映射函數:

delete(m, "key")

第五章

Go是靜態類型語言。

自定義類型字面值:

type user struct {name stringemail string }type admin struct {person userlevel string }u1 := user{"Lisa", "lisa@abc.com"} u2 := user{name: "Lisa", email: "lisa@abc.com"} a1 := admin{person: user{"Lisa", "lisa@abc.com"}level: "super" }

以指針為接收者的函數只能通過指針調用。以值為接收者的函數可以通過值或指針調用。對于以值為接收者的函數,函數域中的接收者是值的副本,即使通過指針調用時也是如此。

package mainimport ("log" )func main() {u1 := user{"Tom"}u2 := &user{"Jerry"}u1.Name()u2.Name()log.Printf("%p %p", &u1, u2) }type user struct {name string }func (r user) Name() {log.Printf("%s %p %p", r.name, &r, &r.name) }

如果函數需要修改接收者的狀態,要以指針作為接收者。否則使用值作為接收者。

Go中的引用類型有:切片、映射、通道、接口和函數。

接口是用于定義行為的類型。如果一個類型實現了某個接口所聲明的全部方法,這個類型的對象就可以賦值給做對應接口類型的變量。在賦值完成后, 會建立一個接口對象。接口對象包含兩個指針:一個指向iTable,一個指向存儲的值。iTable包含了存儲值的類型信息,以及與這個值相關聯的一組方法,稱為方法集。方法集定義了接口的接收規則。

方法接收者
T(t T)
*T(t T) 和 (t?*T)

嵌入類型:

type user struct {name stringemail string }func (r user) hello() string {return "hello " + r.name }type admin struct {userlevel string }a := admin{} a.user.name a.name a.user.hello() a.hello()

被嵌入的類型也叫內部類型。內部類型中的標志符(成員和函數)會被提升到外部類型中。

以小寫字母開頭的標識符是包私有標識符,在包外不可見。對于未公開的內部類型,其公開成員可以通過標識符提升,以外部類型成員的方式訪問。

第六章

Go使用的同步模型是通信順序模型(Communicating Sequential Processes,CSP),各個goroutine通過傳遞消息通信,而非通過鎖和共享內存來共享狀態。

Go運行時會在邏輯處理器上調度goroutine。從1.5版本起,Go運行時會為每個物理處理器分配一個邏輯處理器(每個CPU一個還是每個核一個?)。當goroutine指定到一個阻塞的系統調用時,運行時將線程和goroutine從邏輯處理器上分離。被分離的線程會繼續阻塞,等待系統調用返回。而邏輯處理器會建立一個新線程,從隊列中選取一個goroutine,將新線程和goroutine綁定到邏輯處理器上。

在處理網絡I/O時,goroutine會集成到網絡輪詢器的運行時。

Go運行時的線程數量默認為10000。超過這個數量時,運行時會崩潰。使用runtime/debug包中的方法SetMaxThreads()可以提高線程數量。

并發concurrency不是并行parallelism。并行是讓不同的代碼片段同時在不同的物理處理器上執行。并行指同時處理很多事情。并發指同時管理很多事情。

調用runtime包的方法GOMAXPROCS()可以設置Go運行時邏輯處理器數量。

next:for i := 0; i < 10; i++ {for j := 0; j < 10; j++ {if cond {continue next}}}

runtime.NumCPU()返回物理處理器數量。

runtime.Gosched()從線程退出,并放回隊列。

unbuffered := make(chan int) // 無緩沖區的通道 buffered := make(chan int, 10) // 有緩沖區的通道

無緩沖區通道要求發送方和接收方同時準備好。如果一方沒有準備好,另一方會阻塞。

package mainimport ("fmt" )func main() {input := make(chan int)go func() {input <- 1}()foo(input, 10) }func foo(input chan int, end int) {x := <-inputfmt.Println(x)if x >= end {return}go foo(input, end)input <- x + 1 }

第七章

import ("os""os/signal" )signalQueue := make(chan os.Signal) signal.Notify(signalQueue, os.Interrupt) # 接收信號 for {if interrupted() {break}// ... }func interrupted() bool {select {case <-signalQueue:signal.Stop(signalQueue) # 停止接收信號return truedefault:return false} } a := []int{1, 2} func add(arr ...int) {b := append(a, arr...) }

判斷超時和終端的示例:

interrupt := make(chan os.Signal, 1) complete := make(chan error) timeout := time.After(3 * time.Second)signal.Notify(r.interrupt, os.Interrupt) go func() {complete <- someFunc() }()select { case err := <-complete:return err case <-r.timeout:return "timeout" }

每個調用signal.Notify(signalChan, signum)的隊列,都會收到信號。

第八章

import "log"log.SetPrefix("TRACE: ") log.SetFlags(log.Ldata | log.Llongfile) // Ldate Ltime Llongfile Lmicroseconds Lshortfile // LstdFlags = Ldate | Ltime log.Println("abc") log.Fatalln("abc") log.Panicln("abc")log.New(ioutil.Discard, "TRACE: ", log.LstdFlags|log.Lshortfile) log.New(io.MultiWriter(file, os.Stderr), "ERROR: ", log.LstdFlags|log.Lshortfile)

iota關鍵字為每個常量復制相同的表達式,并且每次自增1:

const (a = 1 << iota // 1b // 2c // 4 )const (x = iota // 0y // 1z // 2 )

第九章

單元測試示例:

import "testing"func TestFoo(t *testing.T) {t.Log("abc")t.Logf("a = %v", 2)t.Errorf("%v", 123)t.Fatal("abc") }

測試web服務示例:

import ("testing""net/http""net/http/httptest" )feed := `<xml ...>`func MockServer() *httptest.Server {return httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {w.WriteHeader(200)w.Header().Set("Content-Type", "application/xml")fmt.Fprintln(w, feed)})) }func TestFoo(t *testing.T) {server := mockServer()defer server.Close()resp, err := http.Get(server.URL)if err != nil {t.Fatal(err)}defer resp.Body.Close()// ... }

測試web服務示例:

http.HandleFunc("/some", func(rw http.ResponseWriter, r *http.Request) {// ... })func TestSome(t *testing.T) {req, _ := http.NewRequest("GET", "/some", nil)rw := httptest.NewRecorder()http.DefaultServeMux.ServeHTTP(rw, req) }

基準測試:

func BenchmarkSprintf(b *testing.B) {number := 10b.ResetTimer()for i := 0; i < b.N; i++ {fmt.Sprintf("%d", number)} }

修訂記錄

  • 2017年08月02日 建立文檔。
  • 2017年08月05日 增加筆記。
  • 2017年08月07日 修正拼寫錯誤。
  • 轉載于:https://my.oschina.net/u/131191/blog/1505533

    總結

    以上是生活随笔為你收集整理的Go语言实战读书笔记的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。