1.常用命令
- go get 获取远程包
- go run 直接运行程序
- go build 测试编译,检查是否有编译错误
- go fmt 格式化源码(部分IDE在保存时自动调用)
- go install 编译包文件并编译整个程序
- go test 运行测试文件
- go doc 查看文档
2.第一个go程序
package main
import (
"fmt"
)
func main() {
fmt.Println("hello 世界!")
}
控制台输出:
➜ go run test.go
hello 世界!
3.基础知识点
- Go程序是通过package来组织的
- 只有package名称为main的包可以包含main函数
- 一个可执行程序有且仅有一个main包
- 通过import关键字来导入其他非main包
package main //当前程序的包名,必须写在第一行
import "fmt" //import关键字导入其他的包
import abc "fmt" //包别名,用abc替换fmt
import(
"fmt" //多个包用()
"time"
)
const PI = 3.14 //常量的定义
var name = "yuanmie" //全局变量的声明与赋值
type newType int //一般类型声明
type gopher struct{} //结构的声明
type golang interface{} //接口的声明
func main() { //由main函数作为程序入口点启动
fmt.Println("hello 世界!")
}
导入包之后,就可以使用 <包名>.<函数名>来对包中的函数进行调用,例如:
func main() {
fmt.Println("hello 世界!")//fmt是包名,Println是函数名
}
如果导入包之后未调用其中的函数或者类型将会报出编译错误
package main
import (
"fmt"
"time" //导入了time包,但是没调用就会报错
)
func main() {
fmt.Println("hello 世界!")
}
控制台:
➜ gogogo go run test.go
# command-line-arguments
./test.go:9: imported and not used: "time"
4.可见性规则
Go语言中,使用大小写来决定该常量,变量,类型,接口,结构或函数是否可以被外部包所调用,根据规定:
- 函数名首字母小写,即为private私有的,不可被外部调用
- 函数名首字母大写,即为public共有的,可以被外部调用
5.基本类型
- 布尔型:bool 长度:1字节
取值范围:true, false
注意事项:不可以用数字代表true或false - 整型:int/uint
根据运行平台可能为32或64位 - 8位整型:int8/uint8
长度:1字节
取值范围:-128 ~ 127 / 0~255 - 16位整型:int16/uint16
长度:2字节
取值范围:-32768 ~ 32767 / 0~65535 - 32位整型:int32(rune别名)/uint32
长度:4字节
取值范围:-2^32/2 ~ 2^32/2-1 / 0 ~ 2^32-1 - 64位整型:int64/uint64
长度:8字节
取值范围:-2^64/2 ~ 2^64/2-1 / 0 ~ 2^64-1 - 字节型:byte(uint8别名)
- 浮点型:float32/float64
长度:4/8字节
小数位:精确到7/15小数位 - 复数:complex64/complex128
长度:8/16字节 - 足够保存指针的 32 位或 64 位整数型:uintptr
- 其它值类型:array、struct、string(数组,结构,字符串)
- 引用类型:slice、map、chan(切片,类似于哈希表,通道:用于并发)
- 接口类型:inteface
- 函数类型:func
类型零值 :
零值并不等于空值,而是当变量被声明为某种类型后的默认值, 通常情况下值类型的默认值为0,bool为false,string为空字符串
func main() {
var a int
var b bool
fmt.Println(math.MaxInt8) //127
fmt.Println(a) //0
fmt.Println(b) //false
}
类型别名
type (
byte int8
rune int32
xxx string //xxx替代string
)
func main() {
var a xxx; //变量a就是字符串类型
a = "hahaha"
fmt.Println(a)//0
}
6.变量
单个变量的声明与赋值
var a int; //变量的声明
a = 1; //变量的赋值
var b int = 123; //声明同时赋值
var c = 234; //省略变量类型,由系统推断
d := 456//简写,全局声明变量不可以简写,只有方法内声明才可以简写
多个变量的声明与赋值
- 全局变量的声明可使用 var() 的方式进行简写
- 全局变量的声明不可以省略 var,但可使用并行方式
- 所有变量都可以使用类型推断
- 局部变量不可以使用 var() 的方式简写,只能使用并行方式
// var (
// a = 1
// b = 2
// c = 3
// d = 4
// )
func main() {
//var a, b, c, d = 1,2,3,4
a, b, c, d := 1,2,3,4
fmt.Println(a) //1
fmt.Println(b) //2
fmt.Println(c) //3
fmt.Println(d) //4
}
变量的类型转换
- Go中不存在隐式转换,所有类型转换必须显式声明
- 转换只能发生在两种相互兼容的类型之间
package main
import (
"fmt"
"strconv"
)
func main() {
var a float32 = 100.111;
fmt.Println(a); //100.111
b := int(a);
fmt.Println(b); //100
var c bool = true;
d := int(c)//转换不了,无法通过编译
var a int = 65;
b := string(a);
c := strconv.Itoa(a);
fmt.Println(a) //64
fmt.Println(b) //A
fmt.Println(c) //65
//string() 表示将数据转换成文本格式,因为计算机中存储的任何东西
//本质上都是数字,因此此函数自然地认为我们需要的是用数字65表示
//的文本 A。
//引入strconv包,调用strconv包里的Itoa方法就会打印出65,而不是转成A
}
7.常量
常量的定义
- 常量的值在编译时就已经确定
- 常量的定义格式与变量基本相同
- 等号右侧必须是常量或者常量表达式
- 常量表达式中的函数必须是内置函数
- 常量规范最好大写
常量的初始化规则与枚举
- 在定义常量组时,如果不提供初始值,则表示将使用上行的表达式
const(
a = 1;
b
)
func main() {
fmt.Println(a) //1
fmt.Println(b) //1
}
- 使用相同的表达式不代表具有相同的值
- iota是常量的计数器,从0开始,组中每定义1个常量自动递增1
- 通过初始化规则与iota可以达到枚举的效果
- 每遇到一个const关键字,iota就会重置为0
const(
a = 'A'
b = iota
c = 'B'
d = iota
)
const(
e = iota
)
func main() {
fmt.Println(a) //65
fmt.Println(b) //1
fmt.Println(c) //66
fmt.Println(d) //3
fmt.Println(e) //0
}
8.运算符
Go中的运算符均是从左至右结合
func main() {
fmt.Println(1 << 10) //左移 1024
}
/*
6 : 0110
11: 1011
--------------------
& 0010 都为1,才为1 2
| 1111 有一个1,就为1 15
^ 1101 只有一个1时候才为1 13
&^ 0100 第二个数为1时,第一个相对应的数强制变为0 4
*/
func main() {
fmt.Println(6 & 11) //2
fmt.Println(6 | 11) //15
fmt.Println(6 ^ 11) //13
fmt.Println(6 &^ 11) //4
}
demo
结合常量的iota与<<运算符实现计算机储存单位的枚举
const(
B float64 = 1 << (iota * 10)
KB
MB
GB
)
func main() {
fmt.Println(B) //1
fmt.Println(KB) //1024
fmt.Println(MB) //1.048576e+06
fmt.Println(GB) //1.073741824e+09
}
9.指针
- Go 拥有指针。指针保存了值的内存地址。
- 类型 *T 是指向 T 类型值的指针。其零值为 nil。
var p *int
- & 操作符会生成一个指向其操作数的指针。
i := 42
p = &i
- *操作符表示指针指向的底层值。
fmt.Println(*p) // 通过指针 p 读取 i
*p = 21 // 通过指针 p 设置 i
- 这也就是通常所说的“间接引用”或“重定向”。
Go虽然保留了指针,但与其它编程语言不同的是,在Go当中不支持指针运算以及”->”运算符,而直接采用”.”选择符来操作指针目标对象的成员
func main() {
a := 1
var p *int = &a
fmt.Println(p) //0xc42000e218 指向的是p的内存地址
fmt.Println(*p) //1
}
func main() {
i, j := 42, 27
p := &i // 指向 i
fmt.Println(*p)
*p = 21 // 通过指针 p 设置 i
fmt.Println(i) // i变成了新的值
p = &j // 指向 j
*p = *p / 3 // 通过指针 p 设置 j
fmt.Println(j) // j变成了新的值
}
结果:
42
21
9