go语言学习
ggaofengg · · 1332 次点击 · · 开始浏览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返回指针
有疑问加站长微信联系(非本文作者)
入群交流(和以上内容无关):加入Go大咖交流群,或添加微信:liuxiaoyan-s 备注:入群;或加QQ群:692541889
关注微信- 请尽量让自己的回复能够对别人有帮助
- 支持 Markdown 格式, **粗体**、~~删除线~~、
`单行代码` - 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
- 图片支持拖拽、截图粘贴等方式上传
收入到我管理的专栏 新建专栏
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返回指针