gostudy
go语⾔有⼀个获取远程包的⼯具就是go get,⽬前go get⽀持多数开源社区(例如:GitHub、googlecode、bitbucket、Launchpad)
这个命令在内部实际上分成了两步操作:第⼀步是下载源码包,第⼆步是执⾏go install
go get github/astaxie/beedb
go get -u 参数可以⾃动更新包,⽽且当go get的时候会⾃动获取该包依赖的其他第三⽅包
go test
执⾏这个命令,会⾃动读取源码⽬录下⾯名为*_的⽂件,⽣成并运⾏测试⽤的可执⾏⽂件。
-v显⽰测试的详细命令
godoc
godoc -http=:8080
浏览器中打开127.0.0.1:8080,会看到⼀个的本地copy版本,可以查询pkg⽂档等其它内容
详解
package <pkgName>(在我们的例⼦中是package main)这⼀⾏告诉我们当前⽂件属于哪个包,⽽包名main则告诉我们它是⼀个可独⽴运⾏的包,它在编译后会产⽣可执⾏⽂件。除了main包之外,其它的包最后都会⽣成*.a⽂件(也就是包⽂件)并放置
在$GOPATH/pkg/$GOOS_$GOARCH中(以Mac为例就是$GOPATH/pkg/darwin_amd64)。
每⼀个可独⽴运⾏的Go程序,必定包含⼀个package main,在这个main包中必定包含⼀个⼊⼝函数main,⽽这个函数既没有参数,也没有返回值。
函数是通过<pkgName>.<funcName>的⽅式调⽤的
前⾯提到过,包名和包所在的⽂件夹名可以是不同的,此处的<pkgName>即为通过package <pkgName>声明的包名,⽽⾮⽂件夹名。
使⽤var关键字是Go最基本的定义变量⽅式,与C语⾔不同的是Go把变量类型放在变量名后⾯:
_(下划线)是个特殊的变量名,任何赋予它的值都会被丢弃。
Go对于已声明但未使⽤的变量会在编译阶段报错
在Go中,布尔值的类型为bool,值是true或false,默认为false。
错误类型
Go内置有⼀个error类型,专门⽤来处理错误信息,Go的package⾥⾯还专门有⼀个包errors来处理错误:
err := errors.New("emit macho dwarf: elf header corrupted")
if err != nil {
fmt.Print(err)
}
Go程序设计的⼀些规则
⼤写字母开头的变量是可导出的,也就是其它包可以读取的,是公有变量;⼩写字母开头的就是不可导出的,是私有变量。
⼤写字母开头的函数也是⼀样,相当于class中的带public关键词的公有函数;⼩写字母开头的就是有pri
vate关键词的私有函数。
array
array就是数组,它的定义⽅式如下:
var arr [n]type
slice
slice并不是真正意义上的动态数组,⽽是⼀个引⽤类型。slice总是指向⼀个底层array,slice的声明也可以像array⼀样,只是不需要长度。
// 和声明array⼀样,只是少了长度
var fslice []int
注意slice和数组在声明时的区别:声明数组时,⽅括号内写明了数组的长度或使⽤...⾃动计算长度,⽽声明slice时,⽅括号内没有任何字符。
slice是引⽤类型,所以当引⽤改变其中元素的值时,其它的所有引⽤都会改变该值
对于slice有⼏个有⽤的内置函数:
len获取slice的长度
cap获取slice的最⼤容量
append向slice⾥⾯追加⼀个或者多个元素,然后返回⼀个和slice⼀样类型的slice
copy函数copy从源slice的src中复制元素到⽬标dst,并且返回复制的元素的个数
map
map`也就是Python中字典的概念,它的格式为`map[keyType]valueType
// 声明⼀个key是字符串,值为int的字典,这种⽅式的声明需要在使⽤之前使⽤make初始化
var numbers map[string]int
// 另⼀种map的声明⽅式
numbers = make(map[string]int)
使⽤map过程中需要注意的⼏点:
map是⽆序的,每次打印出来的map都会不⼀样,它不能通过index获取,⽽必须通过key获取
map的长度是不固定的,也就是和slice⼀样,也是⼀种引⽤类型
内置的len函数同样适⽤于map,返回map拥有的key的数量
map的值可以很⽅便的修改,通过numbers["one"]=11可以很容易的把key为one的字典值改为11
map和其他基本型别不同,它不是thread-safe,在多个go-routine存取时,必须使⽤mutex lock机制
make、new操作
make⽤于内建类型(map、slice和channel)的内存分配。new⽤于各种类型的内存分配。
new返回指针。
零值
关于“零值”,所指并⾮是空值,⽽是⼀种“变量未填充前”的默认值,通常为0。此处罗列部分类型的 “零值”
int 0
int8 0
int32 0
int64 0
uint 0x0
rune 0 //rune的实际类型是 int32
byte 0x0 // byte的实际类型是 uint8
float32 0 //长度为 4 byte
float64 0 //长度为 8 byte
bool false
string ""
goto
Go有goto语句——请明智地使⽤它。⽤goto跳转到必须在当前函数内定义的标签。
for
Go⾥⾯最强⼤的⼀个控制逻辑就是for,它既可以⽤来循环读取数据,⼜可以当作while来控制逻辑,还能迭代操作。
for a; b; c {
//...
}
a、b和c都是表达式,其中a和c是变量声明或者函数调⽤返回值之类的,b是⽤来条件判断,a在循环开始之前调⽤,c在每轮循环结束之时调⽤。
在循环⾥⾯有两个关键操作break和continue ,break操作是跳出当前循环,continue是跳过本次循环。当嵌套过深的时候,break可以配合标签使⽤,即跳转⾄标签所指定的位置。
break和continue还可以跟着标号,⽤来跳到多重循环中的外层循环
for配合range可以⽤于读取slice和map的数据
由于 Go ⽀持 “多值返回”, ⽽对于“声明⽽未被调⽤”的变量, 编译器会报错, 在这种情况下, 可以使⽤_来丢弃不需要的返回值
函数
函数是Go⾥⾯的核⼼设计,它通过关键字func来声明,它的格式如下:
func funcName(input1 type1, input2 type2) (output1 type1, output2 type2) {
//这⾥是处理逻辑代码
//返回多个值
return value1, value2
}
上⾯的代码我们看出
关键字func⽤来声明⼀个函数funcName
函数可以有⼀个或者多个参数,每个参数后⾯带有类型,通过,分隔
函数可以返回多个值
上⾯返回值声明了两个变量output1和output2,如果你不想声明也可以,直接就两个类型
如果只有⼀个返回值且不声明返回值变量,那么你可以省略包括返回值的括号
如果没有返回值,那么就直接省略最后的返回信息
如果有返回值,那么必须在函数的外层添加return语句
我们知道,变量在内存中是存放于⼀定地址上的,修改变量实际是修改变量地址处的内存。只有add1函数知道x变量所在的地址,才能修
改x变量的值。所以我们需要将x所在地址&x传⼊函数,并将函数的参数的类型由int改为*int,即改为指针类型,才能在函数中修改x变量的值。此时参数仍然是按copy传递的,只是copy的是⼀个指针。
这样,我们就达到了修改x的⽬的。那么到底传指针有什么好处呢?go语言字符串转数组
传指针使得多个函数能操作同⼀个对象。
传指针⽐较轻量级 (8bytes),只是传内存地址,我们可以⽤指针传递体积⼤的结构体。如果⽤参数值传递的话, 在每次copy上⾯就会花费相对较多的系统开销(内存和时间)。所以当你要传递⼤的结构体的时候,⽤指针是⼀个明智的选择。
Go语⾔中channel,slice,map这三种类型的实现机制类似指针,所以可以直接传递,⽽不⽤取地址后传递指针。(注:若函数需改变slice的长度,则仍需要取地址传递指针)
defer
Go语⾔中有种不错的设计,即延迟(defer)语句,你可以在函数中添加多个defer语句。当函数执⾏到最后时,这些defer语句会按照逆序执⾏,最后该函数返回。
Panic和Recover
Go没有像Java那样的异常机制,它不能抛出异常,⽽是使⽤了panic和recover机制。⼀定要记住,你应当把它作为最后的⼿段来使⽤,也就是说,你的代码中应当没有,或者很少有panic的东西。这是个强⼤的⼯具,请明智地使⽤它。那么,我们应该如何使⽤它呢?
Panic
是⼀个内建函数,可以中断原有的控制流程,进⼊⼀个panic状态中。当函数F调⽤panic,函数F的执⾏被中断,但是F中的延迟函数会正常执⾏,然后F返回到调⽤它的地⽅。在调⽤的地⽅,F的⾏为就像调⽤了panic。这⼀过程继续向上,直到发
⽣panic的goroutine中所有调⽤的函数返回,此时程序退出。panic可以直接调⽤panic产⽣。也可以由运⾏时错误产⽣,例如访问越界的数组。
Recover
是⼀个内建的函数,可以让进⼊panic状态的goroutine恢复过来。recover仅在延迟函数中有效。在正常的执⾏过程中,调⽤recover会返回nil,并且没有其它任何效果。如果当前的goroutine陷⼊panic状态,调⽤recover可以捕获到panic的输⼊值,并且恢复正常的执
⾏。
main函数和init函数
Go⾥⾯有两个保留的函数:init函数(能够应⽤于所有的package)和main函数(只能应⽤于package main)。这两个函数在定义时不能有任何的参数和返回值。虽然⼀个package⾥⾯可以写任意多个init函数,但这⽆论是对于可读性还是以后的可维护性来说,我们都强烈建议⽤户在⼀
个package中每个⽂件只写⼀个init函数。
1.点操作
import(
. "fmt"
)
这个点操作的含义就是这个包导⼊之后在你调⽤这个包的函数时,你可以省略前缀的包名
2.别名操作
import(
f "fmt"
)
别名操作顾名思义我们可以把包命名成另⼀个我们⽤起来容易记忆的名字
3._操作
import (
"database/sql"
_ "github/ziutek/mymysql/godrv"
)
_操作其实是引⼊该包,⽽不直接使⽤包⾥⾯的函数,⽽是调⽤了该包⾥⾯的init函数。
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论