1、Go基础mysql
①“调用”就是向被调用函数的参数赋值,执行被调用函数语句,并使用其返回值。git
这样,函数就封装了能够被反复调用的一些语句,根据须要赋值获得不一样的结果。github
② min,max := 0, 100web
var s stringsql
min,max经过赋值引伸声明为int类型,s用var明确声明为string类型。数组
③Go使用字节而不是字符做为字符串的单元。由于Go的字符采用UTF-8编码,是不等长的。app
英文字母数字是1个字节,希腊字母要2个字节,汉字等大写字符集,使用3个以上的字节ide
才能表示。因此字符串取其最小单位。函数
④计算结果的类型与操做数类型相同。 3/2 == 1.工具
⑤Go里面switch默认至关于每一个case最后带有break,匹配成功后不会
自动向下执行其余case,
而是跳出整个switch, 可是可使用fallthrough强制执行后面的case代码
⑥这样,咱们就达到了修改x的目的。那么到底传指针有什么好处呢?
1.传指针使得多个函数能操做同一个对象。
2.传指针比较轻量级 (8bytes),只是传内存地址,咱们能够用指针传递体积大的结构体。若是用参数值传递的话,
在每次copy上面就会花费相对较多的系统开销(内存和时间)。
因此当你要传递大的结构体的时候,用指针是一个明智的选择。
3.Go语言中channel,slice,map这三种类型的实现机制相似指针,
因此能够直接传递,而不用取地址后传递指针。
(注:若函数需改变slice的长度,则仍须要取地址传递指针)
⑦Go语言中有种不错的设计,即延迟(defer)语句,你能够在函数中添加多个defer语句。
当函数执行到最后时,这些defer语句会按照逆序执行,最后该函数返回。
特别是当你在进行一些打开资源的操做时,遇到错误须要提早返回,在返回前你须要关闭相应的资源,
否则很容易形成资源泄露等问题。
在defer后指定的函数会在函数退出前调用。
2、流程和函数
函数做为值、类型
在Go中函数也是一种变量,咱们能够经过type来定义它,它的类型就是全部拥有相同的参数,相同的返回值的一种类型
type typeName func(input1 inputType1 , input2 inputType2 [, ...]) (result1 resultType1 [, ...])
函数做为类型到底有什么好处呢?那就是能够把这个类型的函数当作值来传递,请看下面的例子
package main
import"fmt"
type testInt func(int) bool// 声明了一个函数类型
func isOdd(integer int) bool {
if integer%2 == 0 {
returnfalse
}
returntrue
}
func isEven(integer int) bool {
if integer%2 == 0 {
returntrue
}
returnfalse
}
// 声明的函数类型在这个地方当作了一个参数
func filter(slice []int, f testInt) []int {
var result []int
for _, value := range slice {
if f(value) {
result = append(result, value)
}
}
return result
}
func main(){
slice := []int {1, 2, 3, 4, 5, 7}
fmt.Println("slice= ", slice)
odd := filter(slice, isOdd) // 函数当作值来传递了
fmt.Println("Oddelements of slice are: ", odd)
even := filter(slice, isEven) // 函数当作值来传递了
fmt.Println("Evenelements of slice are: ", even)
}
函数当作值和类型在咱们写一些通用接口的时候很是有用,经过上面例子咱们看到testInt这个类型是一个函数类型,而后两个filter函数的参数和返回值与testInt类型是同样的,可是咱们能够实现不少种的逻辑,这样使得咱们的程序变得很是的灵活。
Panic和Recover
Go没有像Java那样的异常机制,它不能抛出异常,而是使用了panic和recover机制。必定要记住,你应当把它做为最后的手段来使用,也就是说,你的代码中应当没有,或者不多有panic的东西。这是个强大的工具,请明智地使用它。那么,咱们应该如何使用它呢?
Panic
是一个内建函数,能够中断原有的控制流程,进入一个使人恐慌的流程中。当函数F调用panic,函数F的执行被中断,可是F中的延迟函数会正常执行,而后F返回到调用它的地方。在调用的地方,F的行为就像调用了panic。这一过程继续向上,直到发生panic的goroutine中全部调用的函数返回,此时程序退出。恐慌能够直接调用panic产生。也能够由运行时错误产生,例如访问越界的数组。
Recover
是一个内建的函数,可让进入使人恐慌的流程中的goroutine恢复过来。recover仅在延迟函数中有效。在正常的执行过程当中,调用recover会返回nil,而且没有其它任何效果。若是当前的goroutine陷入恐慌,调用recover能够捕获到panic的输入值,而且恢复正常的执行。
下面这个函数演示了如何在过程当中使用panic
var user = os.Getenv("USER")
func init() {
if user == "" {
panic("no value for $USER")
}
}
下面这个函数检查做为其参数的函数在执行时是否会产生panic:
func throwsPanic(f func()) (b bool) {
deferfunc() {
if x := recover(); x != nil {
b = true
}
}()
f() //执行函数f,若是f中出现了panic,那么就能够恢复回来
return
}
Go里面有两个保留的函数:init函数(可以应用于全部的package)和main函数(只能应用于package main)。这两个函数在定义时不能有任何的参数和返回值。虽然一个package里面能够写任意多个init函数,但这不管是对于可读性仍是之后的可维护性来讲,咱们都强烈建议用户在一个package中每一个文件只写一个init函数。
Go程序会自动调用init()和main(),因此你不须要在任何地方调用这两个函数。每一个package中的init函数都是可选的,但package main就必须包含一个main函数。
程序的初始化和执行都起始于main包。若是main包还导入了其它的包,那么就会在编译时将它们依次导入。有时一个包会被多个包同时导入,那么它只会被导入一次(例如不少包可能都会用到fmt包,但它只会被导入一次,由于没有必要导入屡次)。当一个包被导入时,若是该包还导入了其它的包,那么会先将其它包导入进来,而后再对这些包中的包级常量和变量进行初始化,接着执行init函数(若是有的话),依次类推。等全部被导入的包都加载完毕了,就会开始对main包中的包级常量和变量进行初始化,而后执行main包中的init函数(若是存在的话),最后执行main函数。下图详细地解释了整个执行过程:
图2.6 main函数引入包初始化流程图
咱们在写Go代码的时候常常用到import这个命令用来导入包文件,而咱们常常看到的方式参考以下:
import( "fmt")
而后咱们代码里面能够经过以下的方式调用
fmt.Println("hello world")
上面这个fmt是Go语言的标准库,实际上是去GOROOT环境变量指定目录下去加载该模块,固然Go的import还支持以下两种方式来加载本身写的模块:
相对路径
import “./model” //当前文件同一目录的model目录,可是不建议这种方式来import
绝对路径
import “shorturl/model” //加载gopath/src/shorturl/model模块
上面展现了一些import经常使用的几种方式,可是还有一些特殊的import,让不少新手很费解,下面咱们来一一讲解一下究竟是怎么一回事
点操做
咱们有时候会看到以下的方式导入包
import( . "fmt" )
这个点操做的含义就是这个包导入以后在你调用这个包的函数时,你能够省略前缀的包名,也就是前面你调用的fmt.Println("hello world")能够省略的写成Println("hello world")
别名操做
别名操做顾名思义咱们能够把包命名成另外一个咱们用起来容易记忆的名字
import( f "fmt" )
别名操做的话调用包函数时前缀变成了咱们的前缀,即f.Println("hello world")
_操做
这个操做常常是让不少人费解的一个操做符,请看下面这个import
import ( "database/sql" _ "github.com/ziutek/mymysql/godrv" )
_操做实际上是引入该包,而不直接使用包里面的函数,而是调用了该包里面的init函数。