文章目录
包
变量
变量声明
Go 语言变量名由字母、数字、下划线组成,其中首个字符不能为数字。
声明变量的一般形式是使用 var 关键字
var identifier type
var identifier1, identifier2 type
指定变量类型,如果没有初始化,则变量默认为零值
package main
import "fmt"
func main() {
var a = "hello word"
var b string
var c uint8
var d bool
fmt.Println(a) // hello word
fmt.Println(b) // ""
fmt.Println(c) // 0
fmt.Println(d) // false
}
- 数值类型(包括complex64/128)为 0
- 布尔类型为 false
- 字符串为 “”(空字符串)
- 以下几种类型为 nil:
var a *int
var a []int
var a map[string] int
var a chan int
var a func(string) int
var a error // error 是接口
根据值自行判定变量类型
package main
import "fmt"
func main() {
var a = "hello word"
fmt.Println(a)
}
省略 var, 注意 := 左侧如果没有声明新的变量,就产生编译错误
package main
import "fmt"
func main() {
a := "hello word"
fmt.Println(a)
var b int
b := 1 // 会产生编译错误
b,c := 1,2 // 此时不会产生编译错误,因为有声明新的变量,因为 := 是一个声明语句
}
多变量声明
package main
import "fmt"
// 这种因式分解关键字的写法一般用于声明全局变量
var (
g string
h uint8
)
func main() {
var a, b string
a, b = "1", "2", "3"
var c, d = "1", "2"
e, f := "1", "2"
}
值类型和引用类型
所有像 int、float、bool 和 string 这些基本类型都属于值类型,使用这些类型的变量直接指向存在内存中的值:
当使用等号 =
将一个变量的值赋值给另一个变量时,如:j = i
,实际上是在内存中将 i 的值进行了拷贝:
你可以通过 &i 来获取变量 i 的内存地址,例如:0xf840000040(每次的地址都可能不一样)。值类型的变量的值存储在栈中。
内存地址会根据机器的不同而有所不同,甚至相同的程序在不同的机器上执行后也会有不同的内存地址。因为每台机器可能有不同的存储器布局,并且位置分配也可能不同。
更复杂的数据通常会需要使用多个字,这些数据一般使用引用类型保存。
一个引用类型的变量 r1 存储的是 r1 的值所在的内存地址(数字),或内存地址中第一个字所在的位置。
这个内存地址为称之为指针,这个指针实际上也被存在另外的某一个字中。
同一个引用类型的指针指向的多个字可以是在连续的内存地址中(内存布局是连续的),这也是计算效率最高的一种存储形式;也可以将这些字分散存放在内存中,每个字都指示了下一个字所在的内存地址。
当使用赋值语句 r2 = r1 时,只有引用(地址)被复制。
如果 r1 的值被改变了,那么这个值的所有引用都会指向被修改后的内容,在这个例子中,r2 也会受到影响。
基本类型
数字类型
整型
- int8: 有符号8位整型(-128 - 127)
- int16: 有符号16位整型(-32768 - 32767)
- int32: 有符号32位整型(-2147483648 - 2147483647)
- int64: 有符号64位整型(-9223372036854775808 - 9223372036854775807)
- uint8: 无符号8位整型(0 - 255)
- uint16: 无符号16位整型(0 - 65535)
- uint32: 无符号32位整型(0 - 4294967295)
- uint64: 无符号64位整型(0 - 18446744073709551615)
浮点型
- float32: IEEE-754 32位浮点型数
- float64: IEEE-754 64位浮点型数
- complex64: 32 位实数和虚数
- complex128: 64 位实数和虚数
其他数字类型
- byte: 类似 uint8
- rune: 类似 int32
- uint: 32 或 64 位
- int: 与 uint 一样大小
- uintptr: 无符号整型,用于存放一个指针
布尔类型
- bool
字符串类型
- string
结构化的(复合的)类型
- struct
- array
- slice
- map
- channel
只描述类型的行为的
- interface
函数
func functionName() {
}
func printStr(str string) {
fm.Println(str)
}
Go程序的一般结构
- 在完成包的 import 之后,开始对常量、变量和类型的定义或声明。
- 如果存在 init 函数的话,则对该函数进行定义(这是一个特殊的函数,每个含有该函数的包都会首先执行这个函数)。
- 如果当前包是 main 包,则定义 main 函数。
- 然后定义其余的函数,首先是类型的方法,接着是按照 main 函数中先后调用的顺序来定义相关函数,如果有很多函数,则可以按照字母顺序来进行排序。
package main
import (
"fmt"
)
const c = "C"
var v int = 5
type T struct{}
func init() { // initialization of package
}
func main() {
var a int
Func1()
// ...
fmt.Println(a)
}
func (t T) Method1() {
//...
}
func Func1() { // exported function Func1
//...
}
Go 程序的执行(程序启动)顺序如下:
- 按顺序导入所有被 main 包引用的其它包,然后在每个包中执行如下流程:
- 如果该包又导入了其它的包,则从第一步开始递归执行,但是每个包只会被导入一次。
- 然后以相反的顺序在每个包中初始化常量和变量,如果该包含有 init 函数的话,则调用该函数。
- 在完成这一切之后,main 也执行同样的过程,最后调用 main 函数开始执行程序。
类型转换
a := 5.0
b := int(a)
类型 B 的值 = 类型 B(类型 A 的值)
Go 命名规范
干净、可读的代码和简洁性是 Go 追求的主要目标。通过 gofmt 来强制实现统一的代码风格。Go 语言中对象的命名也应该是简洁且有意义的。像 Java 和 Python 中那样使用混合着大小写和下划线的冗长的名称会严重降低代码的可读性。名称不需要指出自己所属的包,因为在调用的时候会使用包名作为限定符。返回某个对象的函数或方法的名称一般都是使用名词,没有 Get...
之类的字符,如果是用于修改某个对象,则使用 SetName
。有必须要的话可以使用大小写混合的方式,如 MixedCaps 或 mixedCaps,而不是使用下划线来分割多个名称。