2 go语言的基础
include
- 内置关键字
- 注释方法
- 代码结构(常量,变量,接口,函数的定义)
- 导入包以及包别名
- 可见性规则
- 小练习
内置关键字(25个均为小写)
- break
- case
- chan
- const
- continue
- default
- defer
- else
- fallthrough
- for
- func
- go
- goto
- if
- import
- interface
- map
- package
- range
- return
- select
- struct
- switch
- type
- var
- cap(x) 切片X的容量或者通道X的缓存容量或者数组的长度。
- close(x) 关闭通道ch(但是用于接受信息的通道是非法的)。不能往通道中发送数据。数据还可以从关闭的通道中接受(例如,任何已发送但未接收的值),并且如果通道中没有值了,接收端得到的将是该通道类型的零值。
- copy(dst,src) 将src切片中的项复制(可能是重叠)到dst切片,如果空间不够则截断;或者将字符串字节S复制到[]byte类型的b中。
- delete(m,k) 从映射m中删除其键为k的项,如果键为空就什么也不做。
- new(T) 一个指向类型T的值指针
注释方法
注释方法和js的一样
- // 单行注释
- /* */ 多行注释
代码结构
- go程序是通过package来组织的(与python类似,通过包来组织)
- 只有package名称为main的包可以包含main函数
- 一个可执行程序有且仅有一个main包
- 通过import 关键字来导入其他非 main包
- 通过const关键字来进行常量的定义
- 通过函数体外部使用var关键字来进行全局变量的声明与赋值
- 通过type关键字来进行结构(struct)或者(interface)的声明
- 通过func关键字进行函数的声明。
代码例子如下:
package main // 当前程序包名,必须写在第一
import "fmt" // 导入其他的包
const PI = 2.14 // 常量定义
var name = "Leo" // 全局变量定义
type newType int // 一般类型声明
type gopher struct{} // 结构的声明 gopher是名字 {} 里面写的是逻辑代码
type golang interface{} // 接口的声明 golang是名字 {} 里面写的是逻辑代码
func main(){
fmt.Println("hellow world!"")
}
导入包
导入包我们除了可以一个一个的import导入进去,也可以import(一堆包名),代码如下:
import "fmt" // 导入其他的包
import "os"
import "time"
import "strings"
// 也可以这样写
import (
"io"
"sync"
)
- 导入进去以后,我们可以就像python那样了,包名.方法名 去使用。
- 如果导入包之后未调用其中的函数或者类型将会报编译错误,这样的话时为快速编译而改进的。如:
imported and not userd: "io"
包(package) 别名
等同于python里面的as ,不建议别名和包名一块使用。
- import cname "fmt"
import std "fmt"
func main() {
std.Println("hellow world!")
}
// 或者如下的例子
import (
"fmt"
t "go_dev/day2/example1/add"
)
func main() {
fmt.Println("Name:", t.Name)
fmt.Println("Age:", t.Age)
}
- import . "fmt"的方法,那么就不需要使用 方法名加上包名了,如下所示:
import . "fmt" // 导入其他的包
func main() {
Println("helddddlow world!")
}
init函数
每个源文件都可以包含一个init函数,在执行main函数之前init函数会被go运行框架执行。
// main
package main
import (
"fmt"
t "go_dev/day2/example1/add"
)
func init() {
fmt.Println("begin to init") // 执行main之前优先执行init函数
}
func main() {
fmt.Println("Name:", t.Name)
fmt.Println("Age:", t.Age)
}
包导入先后顺序
我们知道有init函数,设我们有a,b2个包,,假设我们导入一个的这个a包里面有init函数的时候,且这a个包又导入了另外一个b包,另外一个b包也有init函数,那么他们init函数执行的先后顺序是怎么样的?
我们先看看代码目录结构:
我们先看看代码,从最深层里面的包来看,然后一层一层往外到最外层的main。
f1包
// f1
package fortest // package名字要和目录一样
import (
"fmt"
)
var Age int = 111 // 定义两个变量,看会不会冲掉调用者add里这两个变量
var Name string = "Leo"
func init() {
fmt.Println("init in f1")
fmt.Println("f1.Age", Age)
fmt.Println("f1.Name", Name)
Age = 22
fmt.Println("f1.Age after change", Age)
}
add1包
// add
package add // package名字要和目录一样
import (
"fmt"
_ "go_dev/day2/example1/fortest" // 引用fortest包,加个下划线是因为引用这个包(引用后init函数会起作用)而不想使用他
)
var Name string = "Leo" // 同样两个变量
var Age int = 22
func init() {
fmt.Println("init in add1")
fmt.Println("add1.Name", Name)
fmt.Println("add1.Age", Age)
}
main包
// main
package main // package名字要和目录一样
import (
"fmt"
t "go_dev/day2/example1/add" // 前面加个t表示是给add起了一个别名为t
)
func init() {
fmt.Println("begin to init")
}
func main() {
fmt.Println("Name:", t.Name)
fmt.Println("Age:", t.Age)
}
此时我们运行下main函数试试看,运行命令和打印结果如下:
C:/go/bin/go.exe run main.go
init in f1
f1.Age 111
f1.Name Leo
f1.Age after change 22
init in add1
add1.Name Leo
add1.Age 22
begin to init
Name: Leo
Age: 22
由打印结果可知,我们可以得出下面三个结论
- 由此可见,我们在运行main函数的时候,首先是执行import函数,由于调用了add包,所以先执行add,而add文件里面又调用了fortest,所以最先执行的是fortest里的init函数与声明两个变量
- 虽然这fortest里面的两个变量和add文件里面的两个变量一样,那么是不会冲突的与覆盖的。
- 每个文件被调用的时候首先执行init方法
流程图下图所示:
值类型与引用类型
- 值类型就是传递给一个函数作为参数的时候是值拷贝,函数修改这个值不会影响到原值。
- 引用类型是传递给一个函数作为参数的时候是指针类型,函数修改这个值会影响到原值
全局变量与局部变量的作用域范围
全局与局部的区别就在于作用域,看下代码的代码例子,大家猜猜看输出结果是什么:
// god
package main
import (
"fmt"
)
var g string = "G" // 全局变量是G
func n() {
fmt.Println(g)
}
func m() {
g := "O" // 定义局部变量O
fmt.Println(g)
}
func main() {
n()
m()
n()
}
我们先分析下上面的过程
- 我们先定义了一个g变量,值为G
- 然后我们在n函数里面直接使用了这个g变量
- 我们在m函数里面定义了一个局部变量g,作用域范围只在这个函数。
综合上面三个说的点,打印结果是GOG。
试想下如果把m函数换成下面的代码,输出结果会是啥?
func m() {
g = "O" // 定义局部变量O
fmt.Println(g)
}
g="O"
这个是直接把全局变量修改了O,所以打印结果就是GOO了。
可见性规则
在go语言中,使用大小写来决定该常量、变量、类型、接口、结构或者函数是否可以被外部调用,约定规则如下:
- 函数名首字母小写即为private
- 函数名首字母大写为public
小练习
- 如何同时定义多个常量、全局变量
- 如何同时定义多个类型
代码如下:
// testme
package main
import (
"fmt"
)
// 定义多个常量
const (
PI = 3.14
h1 = "Leo"
w = "Beijing"
)
// 全局变量的声明与赋值
var (
name = "Leo"
Name1 = "ljf"
age = 22
)
// 一般类型的声明
type (
newType int
type1 float32
type2 string
type3 byte
)
func main() {
fmt.Println(PI, w, age)
}