Go语言入门看这一篇就go了

幸运草
幸运草
幸运草
9
文章
0
评论
2020年4月20日21:19:12 评论 96

Go语言的前世今生

谷歌的“20%时间”工作方式,允许工程师拿出20%的时间来研究自己喜欢的项目。语音服务Google Now、谷歌新闻Google News、谷歌地图Google Map上的交通信息等,全都是20%时间的产物。

Go语言最开始也是20%时间的产物。

诞生时间

Go 语言起源 2007 年,并于 2009 年正式对外发布。它从 2009 年 9 月 21 日开始作为谷歌公司 20% 兼职项目,即相关员工利用 20% 的空余时间来参与 Go 语言的研发工作。

其实可以看到,Go语言的历史不算很短。

创始人

该项目的三位领导者均是著名的 IT 工程师:

罗伯特·格瑞史莫(Robert Griesemer)

罗勃特·派克(Rob Pike)

肯尼斯·汤普逊(Ken Thompson)

他们的丰功伟绩自己去Google吧!

大事件

2007 年 :雏形设计

2009 年 :首次公开发布

2010 年 :当选 2009 年年度语言,谷歌投入使用

2011 年 :Google App Engine 支持 Go 语言

使用Go的项目

Docker

Doozer

Gogs

InfluxDB

Juju

Packer

Snappy

Syncthing

Go的开源框架

Beego

Martini


Hello World例子

我们队Go中的hello world并不陌生,因为在测试开发环境的时候,我们就使用过,这里先贴上代码,再一点点进行分析:

packagemainimport"fmt"funcmain(){//Thefirstgoprogramfmt.Println("Hello,World!")}

从上面的简短代码中,我们可以看到一个go程序基本包含几个部分:

- package声明

- 导入packages

- 函数

- 变量

- 表达式

- 注释

下面就根据Hello World例子进行更深入的分析:

package main

main package is the starting point to run the program. Each package has a path and name associated with it.

main是一个特殊的package名字,GO的可执行程序必须在main package下

import “fmt”

“fmt” is a preprocessor command which tell the Go compiler to include files lying in package fmt.

Package fmt包含有格式化I/O函数,类似于C语言的printf和scanf。格式字符串的规则来源于C但更简单一些。

func main()

The next line func main() is the main function where program execution begins.

//The first go program

使用//或是 /**/ 进行注释,这跟C++ Java中的注释是一致的

fmt.Println(…)

fmt.Println(…) is another function available in Go which causes the message “Hello, World!” to be displayed on the screen. Here fmt package has exported Println method which is used to display message on the screen.

// Println 在 Print 的基础上,再向 os.Stdout 中写入一个换行符

func Println(a …interface{}) (n int, err error)

Println以大写字符开始

Notice the capital P of Println method. In Go language, a name is exported if it starts with capital letter. Exported means that a function or variable/constant is accessible to importer of the respective package.

源代码文件中,以大写字母开头的函数才会被导出(外部访问)

不使用分号进行结尾

好了,至此,我们把第一个go程序进行了详尽的分析。接下来更进一步,把上面提到的东西更深一点。

import用法

import的使用方法有两种:

第一

import"fmt"import"math/rand"1212

第二

import("fmt""math/rand")12341234

这里一定要注意,使用的是圆括号而不是花括号。

fmt介绍

官方文档:

https://golang.org/pkg/fmt/


变量

var关键字

go语言使用var关键字来定义变量,但是和c++不同的是,类型放在变量的后面,格式如下:

varvariable_listoptional_data_type;

下面就简单定义几个变量:

vari,j,kintvarc,chbytevarf,salaryfloat32d=42vara,s=100,"abc"//混合变量声明

这里我们需要明确一下,为什么go会把变量的类型写在后面呢?

在c++中您是否记得这样的问题呢:

int*p,q

上面p为指针,q为int类型,给我们造成了很大的困扰。

另外可以已组的形式进行变量定义:

var(x,yinta,s=100,"abc")

上面需要注意的是使用圆括号而不是花括号。

自动类型推断和零初始化

对于普通的变量,go语言也会给我们进行零初始化,避免了在c++中变量为垃圾值。

同样,可以省略变量类型,由编译器推断。

示例代码:

packagemainimport"fmt"funcmain(){vara=1//自动推断a为intvarbint//b初始化为0fmt.Println(a,b)}

省略var的简短模式

有时候,我们可以省略var关键字,使用更加简洁的语法进行变量的定义和初始化:

packagemainimport"fmt"funcmain(){a:=1b,s:=2,"go"fmt.Println(a,b,s)}

这里有个容易被忽略的大坑,就是这种简短模式只能用在函数的内部

看下面的代码:

packagemainimport"fmt"varx=1funcmain(){fmt.Println(&x,x)x:=2//重新定义了局部变量fmt.Println(&x,x)}

输出:

0x160004 1

0x1040a140 2

当你写下下面的代码时候,就会报错,no new variables on left side of :=

y:=1fmt.Println(&y,y)y:=2fmt.Println(&y,y)

未使用的局部变量视为错误

注意,这里说的是局部变量,而不是全局变量:

变量类型

bool

string

int int8 int16 int32 int64

uint uint8 uint16 uint32 uint64 uintptr

byte // alias for uint8

rune // alias for int32

float32 float64

complex64 complex128

注意,没有double,但是有float64

这里就是简单提一下,之后还会进行更详细的关于类型,以及类型之间转换的介绍。


常量

const关键字

跟c++中一样,go中同样具有const关键字,来声明常量。

语法是这样的:

constvariabletype=value;11

下面就是简单的常量定义:

constLENGTHint=10constWIDTHint=51212

同样可以用块的形式声明一系列常量:

package main

import "fmt"

func main() {

const(

LENGTH int = 10

WIDTH int = 8

)

fmt.Println(LENGTH)

}

未使用的常量不会引发编译器错误!!

同样,在声明常量的时候,也可以省略常量的类型,由编译器自动推断:

package main

import "fmt"

const (

Cat = 10

Dog = 20

Bird = 30

)

func main() {

// Use our constants.

fmt.Println(Cat)

fmt.Println(Dog)

fmt.Println(Bird)

}

输出:

10

20

30

另外,需要注意,不能给常量进行重新赋值:

const(Normal=1Medium=2)funcmain(){Medium=3}

错误:cannot assign to Medium

可以一行声明多个常量:

constname,size="carrot",10011

不能读取常量的地址

错误:cannot take the address of y

iota关键字

C++中我们使用enum关键字来定义枚举,但是在go中没有这个关键字,但是为我们提供iota关键字。

iota是优雅的自增量!!!!

this is an enumerator for const creation. The Go compiler starts iota at 0 and increments it by one for each following constant. We can use it in expressions.

直接看看代码:

package main

import "fmt"

const (

Low = 5 * iota

Medium

High

)

func main() {

// Use our iota constants.

fmt.Println(Low)

fmt.Println(Medium)

fmt.Println(High)

}

输出:

0

5

10

如果中断iota,必须显示恢复:

package main

import "fmt"

const (

Low = iota

Medium

High = 100

Super

Band = iota

)

func main() {

// Use our iota constants.

fmt.Println(Low)

fmt.Println(Medium)

fmt.Println(High)

fmt.Println(Super)

fmt.Println(Band)

}

输出:

0

1

100

100

4


流程控制

go中的流程控制,其中包括:

if else

switch

for

goto

break

continue

别等了,没有了while。

if…else…

条件表达式必须是布尔类型

之前提到过,下面的代码会报错:cannot use a (type int) as type bool in assignment

条件表达式可以省略圆括号

左侧的花括号不能另起一行

在go语言的世界中,在也不用因为if后的括号而争论左派还是右派了

else也不能另起一行

错误:syntax error: unexpected else, expecting }

if else一起使用

在if语句中进行初始化

switch

不需要显示的写break

switch后的左侧花括号也不能另起一行

可以在switch后进行初始化

default可以不写在case的最后,但是建议写在case的最后

如果不想break,可以使用fallthrough关键字来向下继续执行case

显示使用break阻止fallthrough

for

for后的表达式也可以省略圆括号

for后的花括号也不能另起一行

使用for代替while

使用for range完成数据迭代

goto

在C++中我们完全看不起goto,也禁止使用,但是在go中挺多地方使用了goto: math/gamma.go

break

用于switch for 等语句,终止整个语句块执行

continue

仅用于for循环,终止后续逻辑,进入下一轮循环。


函数

变量介绍完了,流程控制介绍完了,也该轮到函数了。

go中,使用关键字func进行函数声明:

func function_name( [parameter list] ) [return_types]{

body of the function

}

比如,声明一个函数,交换两个字符串:

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

return y, x

}

函数的左花括号也不能另起一行

package main

import (

"fmt"

"math/rand"

)

func main()

{

fmt.Println("My favorite number is", rand.Intn(10))

}

错误:unexpected semicolon or newline before {

不允许函数内嵌定义

package main

import "fmt"

func main() {

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

return y, x

}

a, b := swap("hello", "world")

fmt.Println(a, b)

}

错误:syntax error: unexpected swap, expecting (

支持多返回值、支持命名返回值

package main

import "fmt"

func split(sum int) (x, y int) {

x = sum * 4 / 9

y = sum - x

return

}

func main() {

fmt.Println(split(17))

}

函数只能判断是否为nil

什么是nil?

In Go, nil is the zero value for pointers, interfaces, maps, slices, channels and function types, representing an uninitialized value.

package main

import "fmt"

func add(a, b int) int {

return a + b

}

func main() {

fmt.Println(add == nil)

//fmt.Println(add == 1) //错误 mismatched types func(int, int) int and int)

}

参数视为局部变量,因此不能声明同名变量

package main

import "fmt"

func add(a, b int) int {

a := 2

var b int

return a + b

}

func main() {

fmt.Println(add(1,2))

}

错误:

no new variables on left side of :=

b redeclared in this block

不支持默认参数、已”_”命名的参赛也不能忽略

package main

import "fmt"

func add(a, b int, _ bool) int {

return a + b

}

func main() {

fmt.Println(add(1,2, true))

//fmt.Println(add(1,2) // 错误:not enough arguments in call to add

}

支持可变参数

package main

import "fmt"

func test(str string, a ...int) {

fmt.Println("%T, %v ", str, a)

}

func main() {

test("a", 1, 2, 3)

}

输出:a [1 2 3]

可以在函数内定义匿名函数

package main

import "fmt"

func main() {

func (s string) {

fmt.Println(s)

} ("hello, go!")

}

输出:hello, go!

闭包

这里就简答介绍一下闭包的语法:

package main

import "fmt"

// This function `intSeq` returns another function, which

// we define anonymously in the body of `intSeq`. The

// returned function _closes over_ the variable `i` to

// form a closure.

func intSeq() func() int {

i := 0

return func() int {

i += 1

return i

}

}

func main() {

// We call `intSeq`, assigning the result (a function)

// to `nextInt`. This function value captures its

// own `i` value, which will be updated each time

// we call `nextInt`.

nextInt := intSeq()

// See the effect of the closure by calling `nextInt`

// a few times.

fmt.Println(nextInt())

fmt.Println(nextInt())

fmt.Println(nextInt())

// To confirm that the state is unique to that

// particular function, create and test a new one.

newInts := intSeq()

fmt.Println(newInts())

}

特别声明:以上文章内容仅代表作者本人观点,不代表变化吧观点或立场。如有关于作品内容、版权或其它问题请于作品发表后的30日内与变化吧联系。

转载请注明:{{title}}-变化吧
  • 赞助本站
  • 微信扫一扫
  • weinxin
  • 赞助本站
  • 支付宝扫一扫
  • weinxin
幸运草
Go语言中的常量 函数代码

Go语言中的常量

1 概述 常量,一经定义不可更改的量。功能角度看,当出现不需要被更改的数据时,应该使用常量进行存储,例如圆周率。从语法的角度看,使用常量可以保证数据,在整个运行期间内,不会被更改。例如当前处理器的架构...
Go语言的接口 函数代码

Go语言的接口

Go语言-接口 在Go语言中,一个接口类型总是代表着某一种类型(即所有实现它的类型)的行为。一个接口类型的声明通常会包含关键字type、类型名称、关键字interface以及由花括号包裹的若干方法声明...
Go语言支持的正则语法 函数代码

Go语言支持的正则语法

1 字符 语法 说明 . 任意字符,在单行模式(s标志)下,也可以匹配换行 字符类 否定字符类 d Perl 字符类 D 否定 Perl 字符类 ASCII 字符类 否定 ASCII 字符类 pN U...
Go语言的包管理 函数代码

Go语言的包管理

1 概述 Go 语言的源码复用建立在包(package)基础之上。包通过 package, import, GOPATH 操作完成。 2 main包 Go 语言的入口 main() 函数所在的包(pa...