博主在开发C/C++程序过程中,遇到的许多语法繁琐困扰,在学习GOLANG时。都予以解答。GOLANG的语法特性让我惊喜。
本文会忽略一些语法通识,如果你有C或者C++语言基础,你可以阅读博主的学习笔记让你快速对golang的语法有认知。如果你是新手,建议阅读《go圣经》来完成你的入门。
golang提供代码风格格式化工具gofmt,运行命令【gofmt -w 目标文件】,会对目标文件代码风格做自动格式化操作。一般IDE工具在保存源码时,会自动对代码风格做格式化。
golang提供“os”package用于获取程序输入参数,有点像C中的main(int agrc, char agrv)。通过os.Args这个string slice变量来获取入参,
os.Args[0]为命令本身,os.Args[1:]为命令行参数。
package main
import (
"fmt"
"os"
)
func main() {
fmt.Println(os.Args[1:])
}
golang变量关键字为var,定义变量时需声明其变量类型,变量声明时如果未赋值,则自动赋值为二进制零。常见的变量定义方式有:
var a int // a变量自动初始化为0,类型为int
var b = false // y变量自动判断类型为bool,值为false
var c, d string // 同时定义相同类型的多个变量,c,d都为string类型
var e, f = 12, "hello" // 同时定义不同类型的多个变量,e为int型,f为string类型
var ( // 以组的方式进行定义
g, h int
i, j = 1.1, "world"
)
k := 13.1 // 简短模式定义变量,忽略var关键字
l, m := 14.1, "no var" // 简短模式定义变量,忽略var关键字
简短模式定义变量需要注意三个点:1)定义变量,同时显示初始化 2)不能提供数据类型 3)只能用在函数内部,不能作为全局变量的定义方式。
package main
import "fmt"
var a = 1
func main() {
fmt.Println(&a, a) // 打印全局变量a的地址和值
a := 2 // 定义了一个局部变量a,并赋值为2
fmt.Println(&a, a) // 由于局部变量优先级高于全局变量,这里打印的是局部变量a的地址和值
}
当然,也并不是每次调用简短模式都会重新定义一个局部变量,假设在同一个作用域,之前已经定义过该变量,且使用简短模式【:=】时,左边有新定义的变量,则简短模式只会对已定义的变量值进行重新赋值操作。
package main
import (
"fmt"
"os"
)
func main() {
a, err := os.Open("var.go") //简短模式定义了err变量
fmt.Println(a, err, &err)
buf := make([]byte, 1024)
n, err := a.Read(buf) // 由于n为新定义的变量,err变量在局部变量中已定义,则对err进行重新赋值
fmt.Println(n, err, &err)
}
golang常亮关键字为const,常量在定义时需明确其类型和数值,在定义后不允许修改。需要注意的是,常量在程序编译器预处理阶段,
直接展开作为指令数据使用,常量不被分配内存空间,因此常量无法通过&来获取其地址,常见的常量定义方式:
package main
import "fmt"
func main() {
const a = 3.14
const b, c int = 1, 2
const (
d bool = true
e // 以组定义时,e类型和值和上一行d一致
f int = 4
g // 以组定义时,g类型和值和上一行f一致
)
fmt.Println(a, b, c, d, e, f, g)
}
golang通过关键字iota来实现枚举递增,常见的使用方式:
package main
import "fmt"
func main() {
const (
a = iota // iota默认为int型,值为0
b // int型,值为1
c = 100 // 中断递增 100
d // 100
)
const (
_, _ = iota, iota * 10 // 0, 0*10 int
e, f //1, 1*10 int
g, h //2, 2*10 int
)
const (
_ float32 = iota
i // float型 值为1
)
fmt.Println(a, b, c, d, e, f, g, h, i)
}
golang中空标识符【_】用做忽略占位符使用,可作表达式作值,无法读取其内容。空标识符为预置变量,不可重新定义。
func test(a int) (int, int) {
return 0, a + 1
}
func main() {
_, a := test(1)
fmt.Println(a)
}
golang有26种基础数据类型,跨平台使用无需过多考虑其长度差异
类型 | 长度 (字节) |
默认值 | 说明 |
---|---|---|---|
bool | 1 | fasle | |
byte | 1 | 0 | uint8相同 |
int,uint | 4,8 | 0 | 整数类型,依据平台,可能32或者64位 |
int8,uint8 | 1 | 0 | -128~127,0~255 |
int16,uint16 | 2 | 0 | -32768~32767,0~65535 |
int32,uint32 | 4 | 0 | -4 294 967 296~4 294 967 295, 0~8 589 934 592 |
float32 | 4 | 0.0 | |
float64 | 8 | 0.0 | 默认浮点数类型 |
complex64 | 8 | 复数,实部和虚部都为float | |
complex128 | 16 | 复数,实部和虚部都为float | |
rune | 4 | 0 | int32别名,常用于处理中文字符 |
uintprt | 4,8 | 0 | 足以存储指针的unit |
string | "" | 字符串,默认值为空字符串,而非NULL | |
array | 数组 | ||
struct | 结构体 | ||
function | nil | 函数 | |
interface | nil | 接口 | |
map | nil | 字典,引用类型 | |
slice | nil | 切片,引用类型 | |
channel | nil | 通道,引用类型 |
rune常在开源代码中遇见,用于处理中文字符。golang默认编码为utf8,中文字符占3个字节。而字符默认类型为byte(1个字节)。
在计算时,使用rune类型可以获取字符串长度,而不是占用字节长度。
package main
import "fmt"
func main() {
var buf = "123木头人"
fmt.Println(len(buf))
fmt.Println(len([]rune(buf)))
}