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.go src/pp/qq/ --库目录 package uu kk.go pp.go src/pp/yy/ --库目录 package lul yp.go
import pp "pp/qq" //用pp这个别名代理这个目录的包名uu, import "pp/yy" //这个目录的包为lul fmt.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"] = 2 xx, 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返回指针
有疑问加站长微信联系(非本文作者)