文章目录
  1. 1. 变量及类型推断
  2. 2. 常量
  3. 3. 打印常量和变量
  4. 4. 包和引入
  5. 5. 代码位置
  6. 6. 导入名字
  7. 7. 函数形参名,返回值,被命名的返回值
  8. 8. 指针
  9. 9. 可变性

如果已经有一定的编程基础,那你只需花几个小时就能学会Go编程,因此Go也常被认为是一门“简单易用”的编程语言。Go语言被设计得尽量简洁,它的整个语言规范也一样。在写第一个Go应用之前,我们先来学习Go的一些基础概念。

变量及类型推断

var关键字声明一个变量列表,其中变量的数据类型Type放在变量名的后面,如:

1
2
3
4
5
var(
name string
age int
location string
)

或着将相同类型的变量写在一行并用逗号隔开,
1
2
3
4
var(
name, location string
age int
)

也可以一个一个的声明变量,
1
2
3
var name string
var age int
var location string

也可在var关键字声明的变量列表中初始化变量,
1
2
3
4
5
var(
name string = "Prince Oberyn"
age int = 32
location string = "Dorne"
)

也可以向下面这样声明初始化变量,
1
2
3
var (
name, location, age = "Prince Oberyn", "Dorne", 32
)

在函数内部可以直接用短赋值符号:=来隐式的声明初始化变量,但是这种短赋值符号只能用于声明局部变量,即只能在函数体内使用,如:
1
2
3
4
5
func main() {
name, location := "Prince Oberyn", "Dorne"
age := 32
fmt.Printf("%s (%d) of %s", name, age, location)
}

示例代码
Go语言中,一个变量可以是任意类型,甚至可以将一个函数赋值给一个变量,如:
1
2
3
4
5
6
func main() {
action := func() {
//doing something
}
action()
}

注意: 短赋值符号:=只能用来隐式初始化局部变量,不能在函数体外部使用。

常量

Go语言中,用const关键字声明常量。常量只能是字符,字符串,布尔值或数值。常量初始化可以通过上下文推断它的类型,但是不能使用短赋值符号:=对常量进行声明初始化操作,如:

1
2
3
4
5
6
7
8
9
10
const Pi = 3.14
const (
StatusOK = 200
StatusCreated = 201
StatusAccepted = 202
StatusNonAuthoritativeInfo = 203
StatusNoContent = 204
StatusResetContent = 205
StatusPartialContent = 206
)

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

import "fmt"

const (
Pi = 3.14
Truth = false
Big = 1 << 100
Small = Big >> 99
)

func main() {
const Greeting = "ハローワールド"
fmt.Println(Greeting)
fmt.Println(Pi)
fmt.Println(Truth)
}

示例代码

打印常量和变量

你可以灵活的使用fmt包提供的printprintln函数打印一个常量或变量的值,如:

1
2
3
4
func main() {
cylonModel := 6
fmt.Println(cylonModel)
}

可用fmt.Println换行打印变量,如果要按指定的输出格式打印一个或多个值变量时可以用fmt.Printf函数,如:
1
2
3
4
5
func main() {
name := "Caprica-Six"
aka := fmt.Sprintf("Number %d", 6)
fmt.Printf("%s is also known as %s",name, aka)
}

包和引入

每个Go程序都是由packages组成的,并且以main包为程序的运行入口,如:

1
2
3
4
package main
func main() {
print("Hello,World!\n")
}

如果写一个可执行程序(相对于库),那需要定义一个main 包的go文件,main包中的main函数就是执行程序的入口。按惯例,包名是相同的导入路径的最后一个元素。例如,引入路径math/rand,是指引入math/路径下的rand包。
引入包示例:
1
2
import "fmt"
import "math/rand"

或着引入一个包组:
1
2
3
4
import(
"fmt"
"math/rand"
)

通常,非标准库包使用一个web url作为命名空间,如我将Rails 4中使用的一些用于加密的代码和逻辑移植到Go中,然后将代码包托管到githubrepository上,如:http://github.com/mattetti/goRailsYourself
那现在可以通过下面的方式来引入提交的这个加密包crypto package:
1
import "github.com/mattetti/goRailsYourself/crypto"

代码位置

上面的代码片段只是简单的告诉编译器可以在github.com/mattetti/goRailsYourself/crypto路径下获得crypto这个包,但并不意味着编译器会自动去github仓库中把这个代码拉下来,那到哪里去找到这个crypto代码包呢?
你需要自己去把代码拉下来,最简单的方法是使用Go提供的go get命令,

1
$ go get github.com/mattetti/goRailsYourself/crypto

当安装Go时,我们需要设置GOPATH环境变量, 这个是用来指明二进制执行程序,库文件和你自己代码的存放位置的。执行go get命令,它会把相应的包文件下载到GOPATH指定到路径下。
1
2
$ ls $GOPATH
bin pkg src

bin文件夹中包括Go编译生成到二进制执行文件,你需要将bin文件夹路径添加到你的系统路径中。
pkg文件夹存放编译生成的对应编译版本的所有库文件使得编译器在不需要重新编译的情况下可以重新链接它们。
最后,src文件夹中按引入路径存放着所有Go源码,如:
1
2
$ ls $GOPATH/src
bitbucket.org code.google.com github.com launchpad.net

1
2
$ ls $GOPATH/src/github.com/mattetti
goblin goRailsYourself jet

当新建一个项目时,在src文件夹中推荐按照包引入路径来放置源码文件(如: github.com//)

导入名字

导入一个包后,就可以通过名字来引用导入包中的内容(即在包外可以访问到它到变量,方法及函数等),在Go中,如果名字首字母大写则这个名字,则这个名字可导入的,可以被导入到其它包中使用,即公有的。如FooFOO都是可导入的,而foo则不是可导入的,来看两者的不同:

1
2
3
func main() {
fmt.Println(math.pi)
}


1
2
3
func main() {
fmt.Println(math.Pi)
}

Pi是可以导入的,可以在包外被调用,是公有的,而pi则不可以,编译报错提示:
1
cannot refer to unexported name math.pi

函数形参名,返回值,被命名的返回值

一个函数可以有零个或多个形参,也可以有多个返回值。在形参列表中类型放在形参变量的后面,如:

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

import "fmt"

func add(x int, y int) int {
return x + y
}

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

在下面的示例中,可以将多个类型相同的形参一起声明,如x int, y int可以写成x, y int
1
2
3
4
5
6
7
8
9
10
11
package main

import "fmt"

func add(x, y int) int {
return x + y
}

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

下面示例中,location函数返回两个string类型值。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
func location(city string) (string, string) {
var region string
var continent string

switch city {
case "Los Angeles", "LA", "Santa Monica":
region, continent = "California", "North America"
case "New York", "NYC":
region, continent = "New York", "North America"
default:
region, continent = "Unknown", "Unknown"
}
return region, continent
}

func main() {
region, continent := location("Santa Monica")
fmt.Printf("Matt lives in %s, %s", region, continent)
}

Go语言中,函数可以返回多个值,如果返回参数被命名了,则返回语句可以不需要显示返回相应的返回参数,如:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
func location(name, city string) (name, continent string) {
switch city {
case "New York", "LA", "Chicago":
continent = "North America"
default:
continent = "Unknown"
}
return
}

func main() {
name, continent := location("Matt", "LA")
fmt.Printf("%s lives in %s", name, continent)
}

但是个人推荐,无论返回参数是否被命名了,在返回语句中都显示加上被返回的参数名称

指针

Go语言中有指针,但是没有指针运算。结构字段都可以通过一个结构指针进行访问。Go中指针就像透明的一样,可以用指针直接调用字段和方法。不过Go默认是按值传递参数(值拷贝),如果想通过引用传递参数,则需要传递指针(或使用slicemap等引用结构类型。可以在变量前面加&符号取得这个变量的地址,在变量前面加*符号则可以取得这个变量的值。在Go中方法默认被定义为指针类型而不是值类型(不过方法也可以定义为值类型),通常可以将一个指针赋值给一个变量,如:

1
2
client := &http.Client{}
resp, err := client.Get("http://gobootcamp.com")

可变性

Go中,只有常量在初始化之后是不可改变的。但注意在Go函数中参数默认按值传递,在函数体内修改传入的参数值,并不会改变函数外这个参数的值,如:

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

type Artist struct {
Name, Genre string
Songs int
}

func newRelease(a Artist) int {
a.Songs++
return a.Songs
}

func main() {
me := Artist{Name: "Matt", Genre: "Electro", Songs: 42}
fmt.Printf("%s released their %dth song\n", me.Name, newRelease(me))
fmt.Printf("%s has a total of %d songs", me.Name, me.Songs)
}

results:
1
2
Matt released their 43th song
Matt has a total of 42 songs

上面的结果并没有真正修改me变量中的值,是因为上述形参是通过值传递,如果要达到成功修改,则需要借助指针对me变量进行引用传递,如:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
package main

import "fmt"

type Artist struct {
Name, Genre string
Songs int
}

func newRelease(a *Artist) int {
a.Songs++
return a.Songs
}

func main() {
me := &Artist{Name: "Matt", Genre: "Electro", Songs: 42}
fmt.Printf("%s released their %dth song\n", me.Name, newRelease(me))
fmt.Printf("%s has a total of %d songs", me.Name, me.Songs)
}

上面两个版本中唯一对不同是第一个版本是值传递,只修改了拷贝不影响变量原值,而第二个版本是引用传递,修改的是同一地址上的内容,所以修改成功。

《GO BOOTCAMP》第二章翻译完成,原著第二章出处:Chapter 2 The Basics

作者署名:朴实的一线攻城狮
本文标题:[译]GO BOOTCAMP 第二章:基本概念实战
本文出处:http://researchlab.github.io/2016/01/16/go-basics/
版权声明:本文由Lee Hong创作和发表,采用署名(BY)-非商业性使用(NC)-相同方式共享(SA)国际许可协议进行许可,转载请注明作者及出处, 否则保留追究法律责任的权利。

@一线攻城狮

关注微信公众号 @一线攻城狮

总访问:
总访客: