2 go语言的基础

include

  1. 内置关键字
  2. 注释方法
  3. 代码结构(常量,变量,接口,函数的定义)
  4. 导入包以及包别名
  5. 可见性规则
  6. 小练习

内置关键字(25个均为小写)

  1. break
  2. case
  3. chan
  4. const
  5. continue
  6. default
  7. defer
  8. else
  9. fallthrough
  10. for
  11. func
  12. go
  13. goto
  14. if
  15. import
  16. interface
  17. map
  18. package
  19. range
  20. return
  21. select
  22. struct
  23. switch
  24. type
  25. var
  26. cap(x) 切片X的容量或者通道X的缓存容量或者数组的长度。
  27. close(x) 关闭通道ch(但是用于接受信息的通道是非法的)。不能往通道中发送数据。数据还可以从关闭的通道中接受(例如,任何已发送但未接收的值),并且如果通道中没有值了,接收端得到的将是该通道类型的零值。
  28. copy(dst,src) 将src切片中的项复制(可能是重叠)到dst切片,如果空间不够则截断;或者将字符串字节S复制到[]byte类型的b中。
  29. delete(m,k) 从映射m中删除其键为k的项,如果键为空就什么也不做。
  30. new(T) 一个指向类型T的值指针

注释方法

注释方法和js的一样

  1. // 单行注释
  2. /* */ 多行注释

代码结构

  • 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函数执行的先后顺序是怎么样的?
我们先看看代码目录结构:
img

我们先看看代码,从最深层里面的包来看,然后一层一层往外到最外层的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

由打印结果可知,我们可以得出下面三个结论

  1. 由此可见,我们在运行main函数的时候,首先是执行import函数,由于调用了add包,所以先执行add,而add文件里面又调用了fortest,所以最先执行的是fortest里的init函数与声明两个变量
  2. 虽然这fortest里面的两个变量和add文件里面的两个变量一样,那么是不会冲突的与覆盖的。
  3. 每个文件被调用的时候首先执行init方法

流程图下图所示:

值类型与引用类型

  1. 值类型就是传递给一个函数作为参数的时候是值拷贝,函数修改这个值不会影响到原值。
  2. 引用类型是传递给一个函数作为参数的时候是指针类型,函数修改这个值会影响到原值

全局变量与局部变量的作用域范围

全局与局部的区别就在于作用域,看下代码的代码例子,大家猜猜看输出结果是什么:

// 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

小练习

  1. 如何同时定义多个常量、全局变量
  2. 如何同时定义多个类型

代码如下:

// 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)
}

posted @ 2017-06-11 21:14  温柔易淡  阅读(252)  评论(0编辑  收藏  举报