Golang-1-包、变量和函数

Parts of A Tour Of Go

每个Go程序都是由包构成的。
Go程序从main包开始运行。

1
2
3
4
5
6
7
8
9
10
package main

import (
"fmt"
"math/rand"
)

func main() {
fmt.Println("My favorite number is ", rand.Intn(10))
}

本程序通过导入路径"fmt""math/rand"来使用这个两个包。
按照约定,包名与导入路径的最后一个元素一致,例如:"math/rand"包中的源码均以package rand语句开头。

导入

1
2
3
4
5
6
7
8
9
10
package main

import (
"fmt"
"math"
)

func main() {
fmt.Printf("Now you have %g problems.\n", math.Sqrt(7))
}

分组导入

1
2
3
4
import (
"fmt"
"math"
)

多个导入语句

1
2
import "fmt"
import "math"

推荐使用分组导入的形式

导出名

Go中,如果一个命名是以大写字母开头的,那么它就是已导出的。
在导入一个包时,只能引用其中已导出的命名。任何“未导出”的名字在该包外均无法引用。

1
2
3
4
5
6
7
8
9
10
11
12
13
package main

import (
"fmt"
"math"
)

func main() {
//Error
fmt.Println(math.pi)
//Sucess
fmt.Println(math.Pi)
}

函数

函数可以没有参数或接受多个参数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
package main

import "fmt"

// add 接受两个int型参数
func add(x int, y int) int {
return x + y
}

// 当连续两个或多个函数的已命名形参类型相同时
// 除最后一个类型以外,其它都可以省略
func sub(x, y int) int {
return x - y
}

func main() {
fmt.Println(add(32, 13))
fmt.Println(sub(32, 13))
}

多值返回

函数可以返回任意数量的返回值

1
2
3
4
5
6
7
8
9
10
11
12
package main

import "fmt"

func swap(x, y string) (string, string) {
return y, x
}

func main() {
a, b := swap("Hello", "World")
fmt.Println(a, b)
}

命名返回值

Go的返回值可以被命名,他们会被视作定义在函数顶部的变量。
命名应当有意义。
没有参数的return语句返回已命名的返回值-(直接返回)。
直接返回语句应当较短的函数中,函数较长中的直接返回会影响代码可读性。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
package main

import "fmt"

func split(sum int) (x, y int) {
x = sum*10 + 1
y = sum/10 - 1
// 直接返回
return
}

func main() {
fmt.Println(split(20))
}

变量

var关键字用于声明一个变量列表,跟函数的参数列表一样,变量类型放在最后面。

1
2
3
4
5
6
7
8
9
10
package main

import "fmt"

var c, python, erlang bool

func main() {
var temp int
fmt.Println(temp, c, python, erlang)
}

var既可以在函数外使用,也可以在函数内使用

变量初始化

变量声明的时候可以包含初始值,每个变量对应一个。
如果初始值存在,可以省略变量类型,变量会从初始值中获得类型。

1
2
3
4
5
6
7
8
9
10
package main

import "fmt"

var i, j int = 1, 2

func main() {
var c, python, erlang = true, false, "no!"
fmt.Println(i, j, c, python, erlang)
}

短变量声明

在函数中,可以使用简洁的赋值语句:=代替var声明。

1
2
3
4
5
6
7
8
9
10
package main

import "fmt"

func main() {
var i, j int = 1, 2
k := 3
c, python, erlang := true, false, "no!"
fmt.Println(i, j, k, c, python, erlang)
}

函数外的每个语句都必须以关键字开头,因此:=结构只能在函数内使用。

变量分组声明

1
2
3
4
5
6
7
8
9
10
11
12
13
package main

import "fmt"

var (
x int = 1
y string = "no"
z bool = false
)

func main() {
fmt.Println(x, y, z)
}

同导入语句一样,变量声明也可以分组成一个语法块。

基本类型

当需要一个整数时,请使用int,除非有特殊的理由。

常用类型

Type Desc Default
bool 布尔 false
string 字符串 ""(空字符串)
int 整数(size由系统位数决定) 0

其它基本类型

  • int8
  • int16
  • int32
  • int64
  • uint // 与int一样,size由系统位数决定
  • uint8
  • uint16
  • uint32
  • uint64
  • uintptr // 与int一样,size由系统位数决定
  • byte // uint8的别名
  • rune // int32的别名,表示一个Unicode码点
  • float32
  • float64
  • complex64
  • complex128

零值

没有明确初始值的变量声明会被赋予零值

1
2
3
4
5
6
7
8
9
10
11
package main

import "fmt"

func main() {
var i int
var f float64
var b bool
var s string
fmt.Printf("%v, %v, %v, %q\n", i, f, b, s)
}

类型转换

表达式T(v)将值v转化为类型T

1
2
3
4
5
6
7
8
9
10
11
12
13
package main

import (
"fmt"
"math"
)

func main() {
var i int = 30
var f float64 = math.Sqrt(float64(i * 2))
g := uint(f)
fmt.Println(i, f, g)
}

C不同的是,Go在不同类型的变量之间赋值时需要显式转换(否则编译不通过)。

类型推导

当声明一个变量而不指定类型的时候(x := 123 OR var x = 123),变量的类型由右值推导得出。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
package main

import "fmt"

func main() {
var x = true
y := 12
var z = "hello"
p := 3.14
var q = 0.9 + 1.9i
// %T打印type
fmt.Printf("Type is %T\n", x)
fmt.Printf("Type is %T\n", y)
fmt.Printf("Type is %T\n", z)
fmt.Printf("Type is %T\n", p)
fmt.Printf("Type is %T\n", q)
}

常量

  • 常量的声明与变量类型,只不过是使用const关键字
  • 常量可以是字符、字符串、布尔值或数值
  • 常量不能用:=语法声明
  • 声明常量的同时必须进行初始化,其值不可再次修改
  • 常量在编译期被创建,因此常量在编译期必须能确定其值
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
package main

import "fmt"

const Pi = 3.14

const X, Y = 18, true

const (
P, Q = "string", 19.19
)

func main() {
const (
World = "世界"
Truth = true
)
fmt.Println("Hello", World)
fmt.Println(X, "Years~", Y)
fmt.Println("Say:", P, Q)
fmt.Println("Happy", Pi, "Day")
fmt.Println("Go rules?", Truth)
}

数值常量

一个未指定类型的常量由上下文来决定其类型。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
package main

import "fmt"

const (
// Create a huge number by shifting a 1 bit left 100 places.
// In other words, the binary number that is 1 followed by 100 zeroes.
// 左移
Big = 1 << 100
// Shift it right again 99 places, so we end up with 1<<1, or 2.
// 右移
Small = Big >> 99
)

func needInt(x int) int {
return x*10 + 1
}

func needFloat(x float64) float64 {
return x * 0.1
}

func main() {
fmt.Println(needInt(Small))
fmt.Println(needFloat(Small))
fmt.Println(needFloat(Big))
}