0%

1.基本语法

基础语句

  • 关键字(如func、for)后面的”{“,必须与关键字同行
  • 语句不需要分号结尾,除非有多个语句或声明出现在同一行,跟在语句后的换行符充当了分号的作用

for

1
2
3
4
5
6
7
8
9
10
//go for不需要括号
for i := 1;i<len(os.Args);i++{

}
for _,arg := range os.Args[1:]{

}
//同c中while
for i < 0{
}

if

1
2
3
4
5
6
7
if n > 1{

}else if n > 0{

}else {

}

switch

1
2
3
4
5
6
7
8
9
10
var x,y string
//golang 操作数是非必须的,也不需要break
switch {
case x == "1":
y = "1"
case x == "2":
y = "1"
default: y =
"3"
}

type

1
2
3
4
//类似 typedef
type Point struct{
x,y int
}

变量

1
2
3
4
5
var a int = 1    			
var a int //自动初始为0
var a = 1 //忽略类型,自动适配int类型
var b, c, d = 1, 2.3,"4" //以列表方式声明
value := 1 //短变量声明,支持列表形式,但至少需要声明一个新变量,否则编译报错
  • 局部变量生命周期:动态生命周期,但变量不可访问后,才被垃圾回收器回收。但变量”逃逸“时,其使用堆空间,有垃圾回收器管理与释放

  • 多重赋值:x,y=y,x,两个变量的值直接交换

  • 可赋值性:无隐式类型转换,变量类型必须一致方可赋值,即使是同一底层类型type出来的也不行;但常量较为宽松;不可赋值,同时也不能比较
  • 包内变量的导出:小写开头仅包内可见,大写开头包外可见
  • _:空表示,承接多余的参数

常量

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
const var a int = 1
const var (
b int = 1
c string = "hello world"
d float64 = 'a' //常量与变量不同,常量是允许隐式转换的
)
//一组常量的声明,类型与初始值均被省略,则复用前一项的类型与值
const var(
a = 1
b
)
//const 中 iota 从0开始,逐项加1,从而实现枚举的效果
const var(
_ = 1<<(10*iota)
KB
MB
GB
)

函数

1
2
3
4
5
6
7
8
func name(x,y float) (z,w float){
var f func(int) int //函数指针,初始值nil
f = func(m int) int {
return m+y //匿名函数可以使用外层变量,但是是引用,c++[&]
}// 匿名函数
z = f(x)
return z,w
}

返回值

  • 返回值可以像形参一样命名,建议命名返回值,有利于代码理解,不用专门注释返回值含义
  • 裸返回:若返回值有命名,可以忽略return的操作数

可变参数

1
2
3
4
5
6
7
8
// 声明可变参数:在参数列表最后的类型名称之前使用省略号“…”
func sum(vals ...int){
}
//参数存在slice,传入可变参数:在最后一个参数后面放一个省略号。
values := []int{1,2,3}
sum(0,values...)
//interface{} 类型意味着这个函数的最后一个参数可以接受任何值
func errorf(args ...interface{})

延迟函数调用

1
2
3
4
5
6
7
8
9
10
11
12
13
//defer:在函数前标识,在函数结束后调用,
func fun(a *int) int{
defer insert(a)
// defer a = 10 //语法错误,defer 仅支持函数调用
return *a
}
func insert(a *int){
*a = *a+10;
}
func main() {
a := 1
fmt.Println(fun(&a),a) // 1 11 //先执行return,再执行defer
}

宕机与恢复

  • panic:断言

  • defer:当宕机时,延时函数会倒序执行,直到退回main

  • runtime.Statck :转存储栈,在main中defer,达到生成dump的效果

  • recover:有点类似异常的捕获,终止当前的宕机的状态,并发返回宕机的值,正常返回nil

    1
    2
    3
    4
    5
    6
    7
    8
    defer func(){
    switch p := recover;p{
    case nil://未发生宕机
    case struct{}://预期错误
    default:
    panic(p) //未预期错误,继续宕机
    }
    }

其他

  • golang使用可变长度的函数栈,上限1G
  • 调用匿名函数时,若使用外部变量,需要注意该变量值的变化

声明

  • 每个源文件(.go),使用package声明,该文件属于哪个包:package main
  • main包用来定义独立一个程序,其中的main函数是程序开始的地方
  • 一些包会追加版本号后缀,如“gopkg.in/yaml.v2”。但包名不包含后缀,

导入

  • 使用import导入被调用的包

    1
    2
    3
    4
    5
    6
    import "fmt"
    import "os"
    import (
    "fmt"
    "os"
    )
  • 缺失导入和导入不需要的包,都会编译失败

  • 重命名导入:如果需要导入两个名字一样的包(如math/rand和crypto/rand),至少为其中的一个指定一个替代名字来避免冲突

    1
    2
    3
    4
    import(
    "math/rand"
    crand "crypto/rand"
    )
  • 空导入:没有直接使用包,但需要对包级别的变量执行初始化,以及执行它的init函数时,导入包的语法(正常导入会因第二点编译报错)

    1
    import _ "image/png"
  • 除了标准库,其他包的导入路径以互联网域名作为开始路径

其他

  • 程序启动参数:以os包中的变量Args提供给程序,其格式为os.Args[1:]
  • len():同sizeof()
  • ++i--ij = i++j = i-- 均为非法语句,仅支持i++i--
  • Go的编码格式为Unicode,一般是utf-8

IO函数

输入

1
2
3
4
5
6
7
8
9
//bufio
input := bufio.NewScanner(os.stdin) //构造一个扫描器
for input.Scan(){ //循环扫描一行
text := input.Text() //数据读取
}
//io/ioutil
data,err := ioutil.ReadFile(filename) //从文件中读取
//io.Copy
io.Copy(dts,src) //从字符串中读取

输出

1
2
3
//fmt
fmt.Printf("%d",n) //以f结尾使用类c格式化规则
fmt.Println(n) //ln结尾类似C++的cout

转义字符

  • %v:内置格式的任何值
  • %T:任何值得类型
  • %q:带引号得字符如“a“或者‘a’
  • %t:bool类型
  • %#v:输出时会带上成员变量的变量名
  • 其他同C