一、命名规范
1、golang中的函数名、变量名、常量名、类型名、语句标号和包名等所有的命名,都遵循以下命名规则
①一个名字必须以一个字母(Unicode)字母或下划线开头,后面可以跟任意数量的字母、数字或下划线
②大写字母和小写字母是不同的,如Name和name是两个不同的变量
③关键字和保留字都不建议用作变量名
2、关键字:golang中关键字有25个,关键字不能用于自定义名字,只能在特定语法结构中使用
break default func interface select
case defer go map struct
chan else goto package switch
const fallthrough if range type
continue for import return var
3、保留字:golang中有37个保留字,主要对应内建的常量、类型和函数
内建常量:
true false iota nil
内建类型:
int int8 int16 int32 int64
uint uint8 uint16 uint32 uint64 uintptr
float32 float64 complex128 complex64
bool byte rune string error
内建函数:
make len cap new append copy close delete
complex real imag panic recover
4、注意
①保留字并不是关键字,可以在定义中重新使用它们,在一些特殊的场景中重新定义它们也是有意义的,但是也要注意避免过度而引起语义混乱
②如果一个名字是在函数内部定义,那么它就只在函数内部有效,如果是在函数外部定义,那么将在当前包的所有文件中都可以访问,名字的开头字母的大小写决定了名字在包外的可见性,如果一个名字是大写字母开头的(必须是在函数外部定义的包级名字;包级函数名本身也是包级名字),那么它将是导出的,也就是说可以被外部的包访问,例如fmt包的Printf函数就是导出的,可以在fmt包外部访问,包本身的名字一般总是用小写字母
③名字的长度没有逻辑限制,但是golang的风格是尽量使用短小的名字,对于局部变量尤其是这样,你会经常看到i之类的短名字,而不是冗长的theLoopIndex命名。通常来说,如果一个名字的作用域比较大,生命周期也比较长,那么用长的名字将会更有意义
④在习惯上,golang程序员推荐使用驼峰式命名,当名字由几个单词组成时优先使用大小写分隔,而不是优先用下划线分隔,因此,在标准库有QuoteRuneToASCII和parseRequestLine这样的函数命名,但是一般不会用quote_rune_to_ASCII和parse_request_line这样的命名。而像ASCII和HTML这样的缩略词则避免使用大小写混合的写法,它们可能被称为htmlEscape、HTMLEscape或escapeHTML,但不会是escapeHtml
⑤go文件的名字,建议用下划线的方式命名(参考go源码)
二、变量是什么:变量指定了某存储单元(Memory Location)的名称,该存储单元会存储特定类型的值,在golang中,有多种语法用于声明变量
三、声明变量
1、声明单个变量
package main
import "fmt"
func main() {
var age int // 变量声明
fmt.Println("my age is", age) // 输出:my age is 0
}
/*
语句var age int声明了一个int类型的变量,名字为age,没有给该变量赋值
如果变量未被赋值,golang会自动地将其初始化,赋值该变量类型的零值(Zero Value)
本例中age是int类型,就被赋值为0
*/
2、变量可以赋值为自身类型的任何值
package main
import "fmt"
func main() {
var age int
fmt.Println("my age is", age)
age = 29 // 赋值
fmt.Println("my age is", age) // 输出:my age is 29
age = 54 // 赋值
fmt.Println("my new age is", age) // 输出:my new age is 54
}
3、声明变量并初始化:声明变量的同时可以给定初始值
package main
import "fmt"
func main() {
var age int = 29 // 声明变量并初始化
fmt.Println("my age is", age) // 输出:my age is 29
}
4、类型推断:如果变量有初始值,那么golang能够自动推断具有初始值的变量的类型,因此,如果变量有初始值,就可以在变量声明中省略type
package main
import "fmt"
func main() {
var age = 29 // 可以推断类型为int
fmt.Println("my age is", age) // 输出:my age is 29
}
5、声明多个变量:golang能够通过一条语句声明多个变量
package main
import "fmt"
func main() {
var width, height int = 100, 50 // 声明多个变量
fmt.Println("width is", width, "height is", heigh) // 输出:width is 100 height is 50
}
6、声明不同类型的变量
package main
import "fmt"
func main() {
var (
name = "naveen"
age = 29
height int
)
fmt.Println("my name is", name, ", age is", age, "and height is", height) // 输出:my name is naveen , age is 29 and height is 0
}
7、简短声明
①golang也支持一种声明变量的简洁形式,称为简短声明(Short Hand Declaration),该声明使用了:=操作符,简短声明要求:=操作符左边的所有变量都有初始值
package main
import "fmt"
func main() {
name, age := "naveen", 29 // 简短声明
fmt.Println("my name is", name, "age is", age) // 输出:my name is naveen age is 29
}
②简短声明的语法要求:=操作符的左边至少有一个变量是尚未声明的
package main
import "fmt"
func main() {
a, b := 20, 30 // 声明变量a和b
fmt.Println("a is", a, "b is", b) // 输出:a is 20 b is 30
b, c := 40, 50 // b已经声明,但c尚未声明
fmt.Println("b is", b, "c is", c) // 输出:b is 40 c is 50
b, c = 80, 90 // 给已经声明的变量b和c赋新值
fmt.Println("changed b is", b, "c is", c) // 输出:changed b is 80 c is 90
}
③变量也可以使用表达式进行赋值
package main
import (
"fmt"
"math"
)
func main() {
a, b := 145.8, 543.8
c := math.Min(a, b)
fmt.Println("minimum value is ", c) // 输出:minimum value is 145.8
}
8、由于golang是强类型(Strongly Typed)语言,因此不允许某一类型的变量赋值为其他类型的值
四、变量类型
1、布尔:bool类型表示一个布尔值,值为 true 或者 false
package main
import "fmt"
func main() {
a := true
b := false
fmt.Println("a:", a, "b:", b) // 输出:a: true b: false
c := a && b
fmt.Println("c:", c) // 输出:c: false
d := a || b
fmt.Println("d:", d) // 输出:d: true
}
2、有符号整型
①int8:表示8位有符号整型,-127~127
②int16:表示16位有符号整型,-32768~32767
③int32:表示32位有符号整型,-2147483647~2147483647
④int64:表示64位有符号整型,-9223372036854775807~9223372036854775807
package main
import "fmt"
func main() {
var a int = 89
b := 95
fmt.Println("value of a is", a, "and b is", b) // 输出:value of a is 89 and b is 95
}
package main
import (
"fmt"
"unsafe"
)
func main() {
var a int = 89
b := 95
fmt.Println("value of a is", a, "and b is", b)
fmt.Printf("type of a is %T, size of a is %d", a, unsafe.Sizeof(a)) // 输出:type of a is int, size of a is 4
fmt.Printf("\ntype of b is %T, size of b is %d", b, unsafe.Sizeof(b)) // 输出:type of b is int, size of b is 4
}
/*
在Printf方法中,使用%T格式说明符(Format Specifier),可以打印出变量的类型
golang的unsafe包提供了一个Sizeof函数,该函数接收变量并返回它的字节大小
unsafe包应该小心使用,因为使用unsafe包可能会带来可移植性问题
从上面的输出可以推断出a和b为int类型,且大小都是32位(4字节),如果在64位系统上运行上面的代码,会有不同的输出,在64位系统下,a和b会占用64位(8字节)的大小
*/
3、无符号整型
①uint8:表示8位无符号整型,0~255
②uint16:表示16位无符号整型,0~65535
③uint32:表示32位无符号整型,0~4294967295
④uint64:表示64位无符号整型,0~18446744073709551615
⑤uint:根据不同的底层平台,表示32或64位无符号整型,在32位系统下是0~4294967295,而在64位系统是0~18446744073709551615
4、浮点型
①float32:32位浮点数
②float64:64位浮点数
③整型和浮点型的运用示例
package main
import (
"fmt"
)
func main() {
a, b := 5.67, 8.97
fmt.Printf("type of a %T b %T\n", a, b) // 输出:type of a float64 b float64
sum := a + b
diff := a - b
fmt.Println("sum", sum, "diff", diff) // 输出:sum 14.64 diff -3.3000000000000007
no1, no2 := 56, 89
fmt.Println("sum", no1+no2, "diff", no1-no2) // 输出:sum 145 diff -33
}
/*
a和b的类型根据赋值推断得出,在这里a和b的类型为float64(float64 是浮点数的默认类型)
把a和b的和赋值给变量sum,把b和a的差赋值给diff,接下来打印sum和diff
no1和no2也进行了相同的计算
*/
5、复数类型
①complex64:实部和虚部都是float32类型的的复数
②complex128:实部和虚部都是float64类型的的复数
③内建函数complex用于创建一个包含实部和虚部的复数
func complex(r, i FloatType) ComplexType
/*
该函数的参数分别是实部和虚部,并返回一个复数类型,实部和虚部应该是相同类型,也就是float32或float64
如果实部和虚部都是float32类型,则函数会返回一个complex64类型的复数
如果实部和虚部都是float64类型,则函数会返回一个complex128类型的复数
*/
④还可以使用简短语法来创建复数
c := 6 + 7i
⑤复数应用示例
package main
import (
"fmt"
)
func main() {
c1 := complex(5, 7)
c2 := 8 + 27i
cadd := c1 + c2
fmt.Println("sum:", cadd) // 输出:sum: (13+34i)
cmul := c1 * c2
fmt.Println("product:", cmul) // 输出:product: (-149+191i)
}
/*
c1和c2是两个复数,c1的实部为5,虚部为7。c2的实部为8,虚部为27
c1和c2的和赋值给cadd ,而c1和c2的乘积赋值给cmul
*/
6、其他数字类型
①byte是uint8的别名
②rune是int32的别名
7、字符串类型:在golang中,字符串是字节的集合
①字符串应用示例
package main
import (
"fmt"
)
func main() {
first := "Naveen"
last := "Ramanathan"
name := first +" "+ last
fmt.Println("My name is",name) // 输出:My name is Naveen Ramanathan
}
/*
first赋值为字符串 “Naveen”,last赋值为字符串 “Ramanathan”
+操作符可以用于拼接字符串,拼接了first、空格和last,并将其赋值给name
*/
五、类型转换
1、golang有着非常严格的强类型特征,没有自动类型提升或类型转换,所以无法将两个不同类型的数进行运算
2、可以通过类型转换后再进行运算
package main
import (
"fmt"
)
func main() {
i := 55 // int类型
j := 67.8 // float64类型
sum := i + int(j) // 将j的类型转换为int
fmt.Println(sum) // 输出:122
}
3、赋值的情况也是如此,把一个变量赋值给另一个不同类型的变量,需要显式的类型转换
package main
import (
"fmt"
)
func main() {
i := 10 // int类型
var j float64 = float64(i) // 将i的类型转换为float64
fmt.Println("j", j)
}
六、常量
1、定义
package main
func main() {
const a = 55 // 定义常量
}
2、特性
①常量用于表示固定的值
②常量不能再重新赋值为其他的值
③常量的值会在编译的时候确定,因为函数调用发生在运行时,所以不能将函数的返回值赋值给常量
3、字符串常量
①双引号中的任何值都是golang中的字符串常量
②golang是一门强类型语言,所有的变量必须有明确的类型,而无类型的字符串属于常量
③无类型的常量有一个与它们相关联的默认类型,并且当且仅当一行代码需要时才提供它,如在声明var name = “Sam”时,name需要一个类型,它从字符串常量Sam的默认类型中获取
④也可以创建一个有类型常量
const typedhello string = "Hello World" // typedhello就是一个string类型的常量
⑤golang是一个强类型的语言,在分配过程中混合类型是不允许的
4、布尔常量:布尔常量和字符串常量没有什么不同,他们是两个无类型的常量true和false,字符串常量的规则适用于布尔常量
package main
func main() {
const trueConst = true // 定义布尔常量
var customBool bool = trueConst // 定义变量,将布尔常量赋值给变量
}
5、数字常量
①数字常量包含整数、浮点数和复数的常量,数字常量中有一些微妙之处
②数量常量的类型由语法决定
package main
import (
"fmt"
)
func main() {
var i = 5 // 在语法中是整数
var f = 5.6 // 在语法中是浮点数
var c = 5 + 6i // 在语法中是复数
fmt.Printf("i's type %T, f's type %T, c's type %T", i, f, c) // 输出:i's type int, f's type float64, c's type complex128
}
③示例
package main
import (
"fmt"
)
func main() {
const a = 5
var intVar int = a
var int32Var int32 = a
var float64Var float64 = a
var complex64Var complex64 = a
fmt.Println("intVar",intVar, "\nint32Var", int32Var, "\nfloat64Var", float64Var, "\ncomplex64Var",complex64Var)
}
/*
a的值是5,a的语法是通用的(它可以代表一个浮点数、整数甚至是一个没有虚部的复数),因此可以将其分配给任何兼容的类型,这些常量的默认类型可以被认为是根据上下文在运行中生成的,var intVar int = a要求a是int,所以它变成一个int常量,var complex64Var complex64 = a要求a是complex64,因此它变成一个复数类型
*/
④数字表达式:数字常量可以在表达式中自由混合和匹配,只有当它们被分配给变量或者在需要类型的代码中的任何地方使用时,才需要类型
package main
import (
"fmt"
)
func main() {
var a = 5.9/8
fmt.Printf("a's type %T value %v",a, a) // 输出:a's type float64 value 0.7375
}
/*
5.9在语法中是浮点型,8是整型,5.9/8是允许的,因为两个都是数字常量,除法的结果是0.7375是一个浮点型,所以a的类型是浮点型
*/