這是一個建立於 的文章,其中的資訊可能已經有所發展或是發生改變。
1、包結構與import (http://www.cnblogs.com/sunshiming/p/4928493.html)
go語言規定,一個目錄下,可以放多個.go檔案。
這些.go檔案,必須是相同的package name,一般與目錄名相同,也可以不相同。
實驗如下:src/abc/ --主目錄,package必須是 main,必須有main函數 func main() abc.exe* abc.gosrc/pp/qq/ --庫目錄 package uukk.go pp.gosrc/pp/yy/ --庫目錄 package lulyp.go
import pp "pp/qq" //用pp這個別名代理這個目錄的包名uu,import "pp/yy" //這個目錄的包為lulfmt.Println(pp.F1()) //這裡用包的別名fmt.Println(pp.F2())fmt.Println(lul.Ff3()) //這裡用包名
1、go 工程目錄結構、go build、go install 、GOPATH
開啟git bash
$ mkdir go3
$ export GOPATH=/f/gaofeng/go3/ --必須用export,表示環境變數,然後go才能讀取到這個變數,普通變數子進程是無法讀取的。
亂寫一個包,編譯一下試試
$ go install hesd
can't load package: package hesd: cannot find package "hesd" in any of:
D:\Go\src\hesd (from $GOROOT)
F:\gaofeng\go3\src\hesd (from $GOPATH)
說明不管使用者當前在哪個目錄,go都會到$GOROOT和$GOPATH的src目錄下去找hesd這個檔案夾進行編譯。
然後在src下建立pkg1和pkg2兩個目錄,寫代碼
$ cat src/pkg2/abc.go
package abc
import "fmt"
func Tt(){
fmt.Print("hello2")
}
go build -v pkg2 --可以編譯成功,但是看不到編譯後的pkg2.a檔案
go install -v pkg2 --編譯並安裝,自動在go3目錄下建立了pkg目錄
$ ls pkg/windows_386/
pkg2.a
$ cat src/pkg1/m.go --編寫一個main包,匯入pkg2目錄
package main
import ("pkg2";"fmt")
func main(){
fmt.Print("main")
abc.Tt()
}
go install -v pkg1 --編譯安裝成功,自動建立了bin目錄
$ ls bin/
pkg1.exe*
2、對象編程
func main() {var s = NewStudent2("gaofeng")s.SetName("22")s.Say1()}type say interface {Say1()SetName(name string)}type Student struct {name string}func NewStudent(name string) *Student {//返回指標,只是方便對介面賦值,對介面賦值必須是地址類型return &Student{name}}func NewStudent2(name2 string) *Student {return &Student{name: name2}}func (s Student) Say1() {//s是一份拷貝,s.name="11",只是修改了這個臨時拷貝,沒有修改原對象fmt.Println(s.name, "say1")}func (s *Student) SetName(name string) {//s是一個指標,可以修改對象內容s.name = name}
3、並發編程
func main() {ch1 := make(chan int)ch2 := make(chan int)go ss(ch1, 2)go ss(ch2, 4)fmt.Println(<-ch1)fmt.Println(<-ch2)}func ss(ch1 chan int, data int) {time.Sleep(time.Second * time.Duration(data))ch1 <- data}
4、defer關鍵字
defer resp.Body.Close()如果有多條語句需要執行,可以用一個匿名函數defer func() {fmt.Println("defer") ...}()5、http
import ("fmt""io""net/http""os")func Test1() {resp, err := http.Get("http://www.baidu.com")if err != nil {fmt.Println("err:", err)return}defer resp.Body.Close()io.Copy(os.Stdout, resp.Body)}
curl 127.0.0.1:8080/book?name='ccc'func main() {http.HandleFunc("/book", handle)http.HandleFunc("/", handle2)err := http.ListenAndServe(":8080", nil) //如果監聽服務運行成功,則阻塞在這裡。if err != nil {fmt.Print(err.Error())}}func handle(w http.ResponseWriter, r *http.Request) {time.Sleep(3 * time.Second)r.ParseForm() //預設不解析,Form為空白。解析後,Form中有內容。fmt.Println()fmt.Println(r.Host, r.Method, r.URL)fmt.Println(r.Form)fmt.Println(r.Header)fmt.Fprint(w, "hello world! "+r.Form["name"][0])}func handle2(w http.ResponseWriter, r *http.Request) {r.ParseForm() //預設不解析,Form為空白。解析後,Form中有內容。fmt.Println()fmt.Println(r.Host, r.Method, r.URL)fmt.Println(r.Form)fmt.Println(r.Header)fmt.Fprint(w, "ppp! "+r.Form["name"][0])}
6、錯誤處理
一般用err返回錯誤就可以了。如果發生了嚴重問題,可以panic,然後程式就結束了,稱之為快錯。也可以用recover捕獲panic。
go的錯誤處理機制,官方建議用err,和C差不多。panic+recover的組合類別似於try-catch。
func main() {defer func() {if err := recover(); err != nil {fmt.Println(err)}}()err := httptest.Test2()if err == nil {fmt.Println("OK")} else {fmt.Println(err)}}func Test2() error {fmt.Println(11)//panic("hehe")fmt.Println(22)return nil//return fmt.Errorf("ggg")}
7、map和slice
v7 := make(map[string]int)v8 := map[string]string{"t1": "ttu","t2": "oo",}v7["bb"] = 2xx, ok := v7["bb"] //key是否存在fmt.Println(len(v8), xx, ok)for k, v := range v7 {fmt.Println(k, v)}v9 := []string{"ddd", "rr"}fmt.Println(v9)v10 := make([]string, 5, 10)fmt.Println(len(v10), cap(v10))fmt.Println(v10[4]) //正常fmt.Println(v10[5]) //異常
8、make只能給map、slice、channl分配記憶體; new給所有類型分配記憶體,
new返回指標