【Go Programming Language】golang
一、go run %filename 能夠直接編譯並運行一個文件,期間不會產生臨時文件。例如 main.go。express
go run main.go
二、Package服務器
Go code is organized into packages, which are similar to libraries or modules in other languages. A package consists of one or more .go source files in a single directory that define what the package does.app
The Go standard library has over 100 packages for common tasks like input and output, sorting, and text manipulation. dom
Package main is speci al. It defines a standalone executable program, not a library. Within package main the func tion main is also special—it’s where execution of the program begins.ide
package main import "fmt" func main(){ fmt.Printf("hello, world\n") }
A prog ram will not compile if there are missing imports or if there are unnecessary ones. This strict requirement prevents references to unused packages from accumulating as programs evolve.函數
三、Go does not require semicolons at the end s of statements or declarat ions, except where two or more app ear on the same line.oop
In effect, newlines following certain tokens are converted into semicolons, so where newlines following certain tokens are converted into semicolons.post
token後面跟着換行符會被轉換爲 semicolon。fetch
四、Go takes a strong stance on code formatting . The gofmt tool rewrites code into the standard format, and the go tool’s fmt subcommand applies gofmt to all the files in the specified package, or the ones in the current directory by default.
goimports, addition ally manages the insertion and removal of import declarations as needed. It is not part of the standard distribution but you can obtain it with this command:
$ go get golang.org/x/tools/cmd/goimports
五、os.Args
The os package provides functions and other values for dealing with the operating system in a platform-independent fashion.
os.Args 能夠獲取命令行參數。
os.Args is a slice of strings. a slice as a dynamically sized sequence s of array elements where individual elements can be accessed as s[i] and a contiguous subsequence as s[m:n]. The number of elements is given by len(s). As in most other programming languages, all indexing in Go uses half-open intervals that include the first index but exclude the last, because it simplifies logic. For example, the slice s[m:n], where 0 ≤ m ≤ n ≤ len(s), contains n-m elements.
If m or n is omitted, it defaults to 0 or len(s) respectively, so we can abbreviate the desired slice as os.Args[1:].
六、echo1 示例
package main import ( "fmt" "os" ) func main(){ var s, sep string for i:=1; i<len(os.Args); i++{ s += sep+os.Args[i] sep = "" } fmt.Println(s) }
注意點:
1)一個 import 能夠導入多個 package。
2)變量類型旋轉在變量定義後。
3)for 語句沒有 ()。
4)The := symbol is part of a short variable declaration, a statement that declares one or more variables and gives them appropriate types based on the initializer values;
:= 定義而且賦予初始值。
七、Go 中只有 i++,沒有++i。
八、for循環語法。沒有(),以及必須有{}。
能夠沒有 initialization、post,以下:
下面是無窮循環:
九、echo2示例
package main import ( "fmt" "os" ) func main(){ s,sep:="","" for _,arg:=range os.Args[1:]{ s+=sep+arg sep="" } fmt.Println(s) }
1)range produces a pair of values: the index and the value of the element at that index.
2)blank identifier, whose name is _(an underscore).The blank identifier may be used whenever syntax requires a variable name but program logic does not..
3)several ways to declare a string variable:
4)上述代碼中字符串累加很是的低效,可使用 strings.Join()方法來優化。
十、dup1示例
package main import ( "bufio" "fmt" "os" ) func main(){ counts := make(map[string]int) input:=bufio.NewScanner(ois.Stdin) for input.Scan(){ counts[input.Text()]++ } for line,n:=range counts{ if n>1 { fmt.Printf("%d\t%s\n", n, line) } } }
1)map[string]int,表明key是string類型,value是int類型。加上make() 用於建立一個此類型的map。
2)The order of map iteration is not specified, but in practice it is random. This design is intentional, since it prevents programs from relying on any particular ordering where none is guaranteed.
3)The Scan functino returns true if there is a line and false when there is no more input.
十一、dup2 示例
1 package main 2 3 4 import ( 5 "bufio" 6 "fmt" 7 "os" 8 ) 9 10 func main(){ 11 counts :=make(map[string]int) 12 files:=os.Args[1:] 13 if len(files)==0{ 14 countLines(os.Stdin, counts) 15 }else{ 16 for _,arg:=range files{ 17 f,err:=os.Open(arg) 18 if err!=nil{ 19 fmt.Fprintf(os.Stderr, "dup2:%v\n", err) 20 continue 21 } 22 countLines(f, counts) 23 f.Close() 24 } 25 } 26 for line, n:=range counts{ 27 if n>1{ 28 fmt.Printf("%d\t%s\n", n, line) 29 } 30 } 31 } 32 33 func countLines(f *of.File, counts map[string]int){ 34 input:=bufio.NewScanner(f) 35 for input.Scan(){ 36 counts[input.Text()]++ 37 } 38 }
1)函數調用能夠放置函數定義前。本例中 countLines()函數,比C++強。
2)fmt.Fprintf()函數相似於C++中的fprint。
十二、lissajous 示例
1 package main 2 3 4 import( 5 "image" 6 "image/color" 7 "image/gif" 8 "io" 9 "math" 10 "math/rand" 11 "os" 12 ) 13 14 var palette = []color.Color{color.White, color.Black} 15 16 const ( 17 whiteIndex = 0 18 blackIndex = 1 19 ) 20 21 func main(){ 22 const( 23 cycles = 5 24 res = 0.001 25 size = 100 26 nframes = 64 27 delay = 8 28 ) 29 30 freq:=rand.Float64()*3.0 31 anim:=gif.GIF{LoopCount:nframes} 32 phase:=0.0 33 for i:=0;i<nframes;i++{ 34 rect:=image.Rect(0,0,2*size+1,2*size+1) 35 img:=image.NewPaletted(rect,palette) 36 for t:=0;t<cycles*2*math.Pi;t+=res{ 37 x:=math.Sin(t) 38 y:=math.Sin(t*freq+phase) 39 img.SetColorIndex(size+int(x*size+0.5),size+int(y*size+0.5), 40 blackIndex) 41 } 42 phase+=0.1 43 anim.Delay = append(anim.Delay, delay) 44 anim.Image = append(anim.Image, img); 45 } 46 }
1)import "image/gif",經過 gif 就能直接引用。
2)const (),the valu of const must be a number, string or boolean.
1三、fetch示例
1 package main 2 3 import( 4 "fmt" 5 "io/ioutil" 6 "net/http" 7 "os" 8 ) 9 10 func main(){ 11 for _, url:=range os.Args[1:]{ 12 resp, err := http.Get(url) 13 if err!=nil{ 14 fmt.Fprintf(os.Stderr, "fetch:%v\n", err) 15 os.Exit(1) 16 } 17 18 b,err:=ioutil.ReadAll(resp.Body) 19 resp.Body.Close() 20 if err!=nil{ 21 fmt.Fprintf(os.Stderr, "fetch:reading %s:%v\n", url, err) 22 os.Exit(1) 23 } 24 fmt.Printf("%s", b) 25 } 26 } 27
1)net/http,其中的 http.Get() 方法能夠用於發起一個Http請求,並返回內容。
1四、fetch all 示例
1 package main 2 3 import ( 4 "fmt" 5 "io" 6 "io/ioutil" 7 "net/http" 8 "os" 9 "time" 10 ) 11 12 func main(){ 13 start :=time.Now() 14 ch:=make(chan string) 15 for _,url :=range os.Args[1:]{ 16 go fetch(url, ch) // start a goroutine 17 } 18 19 for range os.Args[1:]{ 20 fmt.Println(<-ch) // receive from channel ch 21 } 22 23 fmt.Printf("%.2fs elapsed\n", time.Since(start).Seconds()) 24 } 25 26 func fetch(url string, ch chan<- string){ 27 start:=time.Now() 28 resp, err:=http.Get(url) 29 if err!=nil{ 30 ch<-fmt.Sprint(err) // send to channel ch 31 return 32 } 33 34 nbytes, err:=io.Copy(ioutil.Discard, resp.Body) 35 resp.Body.Close() 36 if err!=nil{ 37 ch<-fmt.Sprintf("while reading %s:%v", url, err) 38 return 39 } 40 secs:=time.Since(start).Seconds() 41 ch<-fmt.Sprintf("%.2fs %7d %s", secs, nbytes, url) 42 }
1)A goroutine is a concurrent function execution. A channel is a communication mechanism that allows one goroutine to pass values of a specified typ e to another goroutine. The function main runs in a goroutine and the go st atement cre ates addition al goroutines.
2)經過 ch:=make(chan string) 建立一個channel,經過 ch <- str 向 ch中寫入內容,經過 <-ch 從ch中讀取內容
3)經過 go func(),建立一個新 goroutine
1五、server1示例,使用內置的http package,建立一個 http服務器。
1 package main 2 3 import( 4 "fmt" 5 "log" 6 "net/http" 7 ) 8 9 func main(){ 10 http.HandleFunc("/", handle) 11 log.Fatal(http.ListenAndserve("localhost:8000", nil)) 12 } 13 14 func handler(w httpResponseWritter, r *http.Request){ 15 fmt.Fprintf(w, "URL.Path = %q\n", r.URL.Path) 16 }
1)http.ListenAndServer(port) 開啓Http服務,http.HandleFunc(path, func)設置路由。
2)http.Request 表明一個請求。
1六、server2 示例,經過請求 /count 路徑,得到 / 路徑的調用次數。
1 package main 2 3 import( 4 "fmt" 5 "log" 6 "net/http" 7 "sync" 8 ) 9 10 var mu sync.Mutex 11 var count int 12 13 func main(){ 14 http.HandleFunc("/", handler) 15 http.HandleFunc("/count", counter) 16 log.Fatal(http.ListenAndServe("localhost:8000", nil)) 17 } 18 19 func handler(w http.ResponseWritter, r *http.Request){ 20 mu.Lock() 21 count++ 22 mu.Unlock() 23 fmt.Fprintf(w, "URL.Path = %q\n", r.URL.Path) 24 } 25 26 func counter(w http.ResponseWritter, r *http.Request){ 27 mu.Lock() 28 fmt.Fprintf(w, "Count %d\n", count) 29 mu.Unlock() 30 }
1)import "sync", var mu sync.Mutex 用於定義一個互斥鎖。
2)A handler pattern that ends with a slash matches any URL that has the pattern as a prefix.
1七、server3 示例,用於解析 http 請求 Header & FormData。
1 func handler(w http.ResponseWritter, r *http.Request){ 2 fmt.Fprintf(w, "%s %s %s\n", r.Method, r.URL, r.Proto) 3 for k,v:=range r.Header{ 4 fmt.Fprintf(w, "Header[%q] = %q\n", k,v) 5 } 6 7 fmt.Fprintf(w, "Host = %q\n", r.Host) 8 fmt.Fprintf(w, "RemoteAddr=%q\n", r.RemoteAddr) 9 if err:=r.ParseForm(); err!=nil{ 10 log.Printf(err) 11 } 12 for k,v:=range r.Form{ 13 fmt.Fprintf(w, "Form[%q] = %q\n", k, v) 14 } 15 }
1)使用 http.Request.Form 前須要先調用和 http.Request.ParseForm。
2)在前例中,range 用於獲取 [index,value],而本例中 range 用於獲取 [key,value]。
3)if 的條件中可使用多條語句。下述寫法,將 err 的 scope 限制在了 if 語句內。
if err:=r.ParseForm(); err!=nil{ log.Printf(err) }
4)
1八、Named Types
1九、Point ers are explicitly visible. The & operator yields the address of a variable, and the operator retrieves the variable that the * pointer refers to, but there is no point er arithmetic.
20、If an entity is declare d within a function, it is local to that function. If declared outside of a function, however, it is visible in all files of the package to which it belongs.
函數外定義的變量,事個package中全部的file均可以訪問。
package-level entity is visible not only throughout the source file that contains its declaration, but throughout all the files of the package.
2一、The case of the first letter of a name determines its visibility across package boundaries.
If the name begins with an upper-case letter, it is exported, which means that it is visible and accessible outside of its own package and may be refer red to by other par ts of the program, as wit h Printf in the fmt package.
若是變量以大寫字母開頭,則它能夠被包外代碼引用。
Package names themselves are always in lower case. 包名永遠是小寫。
2二、variables. Either the type or the = expression part may be omitted, but not both.
Omitt ing the typ e allows decl arat ion of multiple var iables of different types:
2三、in Go there is no such thing as an uninitialize d variable.
2四、一個函數能夠返回多個返回值。
2五、short variable declaration.
multiple variables may be declared and initialized in the same short variable declaration。
短變量聲明的左邊必須包含至少一個新變量,下左圖是ok的,而下右圖則會編譯錯誤。
:= 只對同一語法塊中的變量起 assignment 做用,語法塊之外的同名變量會被 ignored。
2六、Pointer
Not every value has an address, but every variable does.
It is perfectly safe for a function to return the address of a local variable !!! Each call of f returns a distinct value.
2七、flag package 示例
1 package main 2 3 import( 4 "flag" 5 "fmt" 6 "strings" 7 ) 8 9 var n = flag.Bool("n", false, "omit trailing newline") 10 var sep = flag.String("s", "", "separator") 11 12 func main(){ 13 flag.Parse() 14 fmt.Print(strings.Join(flag.Args(), *sep)) 15 if !*n { 16 fmt.Println() 17 } 18 }
1)flag.Parse() 必須最早調用,默認帶有 -h -help的解釋。
2八、new Function()
The expression new(T) creates an unnamed variable of type T, initializes it to the zero value of T, and returns its address, which is a value of type *T.
A variable created with new is no different from an ordinary local variable whose address is taken, Thus new is only a syntactic convenience, not a fundamental notion.
The two newInt functions below have identical behaviors.
2九、Lifetime of Variables
The lifetime of a package-level variable is the entire execution of the program.
By contrast, local variables have dynamic lifetimes: a new instance is create d each time the declaration statement is executed, and the variable lives on until it becomes unreachable, at which point its storage may be rec ycled.
A compiler may choose to allocate local variables on the heap or on the stack but, perhaps surprisingly, this choice is not determined by whether var or new was used to declare the variable.
變量分配在堆上仍是棧上,由編譯器決定, var、new沒法對此產生影響。
30、Tuple Assignment
3一、Type Declarations
能夠爲自定義類型添加Method。
Many types declare a String method of this form because it controls how values of the type appear when printed as a string by the fmt package.
3二、Packages and Files
Extensive doc comments are often placed in a file of their own, conventionally called go.doc.
use the golang.org/x/tools/cmd/goimports tool, which automatically inserts and removes packages from the import declaration as necessary ; most editors can be configured to run goimports each time you save a file. Like the gofmt to ol, it also pretty-prints Go source files in the canonical format.
3三、Package Initialization
Any file may contain any number of functions whose declaration is just:
init functions are automatically executed when the program starts, in the order in which they are declared.
一個文件能夠包含多個 init() 函數,在執行main()前,會按照聲明的順序依次調用。
3四、不一樣的 lexical block 能夠定義同名變量。 Inner lexical 優先級高於 Outer Lexical。
3五、if scope
The second if statement is nested within the first, so variables declared within the first statement's initializer are visible within the second.
if 中的變量做用範圍限定在 if語句中,因此如下代碼中對 f 的引用會引發編譯錯誤。
爲了解決上述問題,能夠像下面這樣寫代碼(但不推薦):
3六、short variable declaration 要點
下述代碼中, 函數內會新建立一個 local cwd,致使 global cwd 未被初始化。
一種解決方法是,使用 assignment,而不是使用 short variable declaration:
3七、
3八、
3九、
40、