go语言基本语法,数据类型,等基础知识

1. 小案例:

package main 定义了包名

import "fmt" 告诉 Go 编译器这个程序需要使用 fmt 包

func main() { 程序开始执行的函数

/* 这是我的第一个简单的程序 */

fmt.Println("Hello, World!")} 字符串输出到控制台

go语言数据类型:

  1. 布尔型: var b bool = true。
  2. 数据类型: 整数型 int ; 浮点类型: float
  3. 字符串类型:String

(a) 指针类型(Pointer)

  • (b) 数组类型
  • (c) 结构化类型(struct)
  • (d) Channel 类型
  • (e) 函数类型
  • (f) 切片类型
  • (g) 接口类型(interface)
  • (h) Map 类型

变量声明:

Var a int = 10 ;第一种

a :=10 ; 省略var, 注意 :=左侧的变量不应该是已经声明过的,否则会导致编译错误。

多变量声明:

//类型相同多个变量, 非全局变量var vname1, vname2, vname3 type

vname1, vname2, vname3 = v1, v2, v3

var vname1, vname2, vname3 = v1, v2, v3 //和python很像,不需要显示声明类型,自动推断

vname1, vname2, vname3 := v1, v2, v3 //出现在:=左侧的变量不应该是已经被声明过的,否则会导致编译错误

var (

vname1 v_type1

vname2 v_type2 )// 这种因式分解关键字的写法一般用于声明全局变量

注意事项:

如果在相同的代码块中,我们不可以再次对于相同名称的变量使用初始化声明,例如:a := 20 就是不被允许的,编译器会提示错误 no new variables on left side of :=,但是 a = 20 是可以的,因为这是给相同的变量赋予一个新的值。

你可以省略类型说明符 [type],因为编译器可以根据变量的值来推断其类型。

  • 显式类型定义: const b string = "abc"
  • 隐式类型定义: const b = "abc"

多个相同类型的声明:

const c_name1, c_name2 = value1, value2 //const关键字 修饰的数据类型是指常类型,常类型的变量或对象的值是不能被更新的

常量可以用len()字符串长度, cap()数组长度, unsafe.Sizeof()字节长度 函数计算表达式的值

iota,特殊常量,可以认为是一个可以被编译器修改的常量。

在每一个const关键字出现时,被重置为0,然后再下一个const出现之前,每出现一次iota,其所代表的数字会自动增加1。

iota 可以被用作枚举值:

const (

a = iota

b = iota

c = iota)

第一个 iota 等于 0,每当 iota 在新的一行被使用时,它的值都会自动加 1;所以 a=0, b=1, c=2 可以简写为如下形式:

例子1:const (

a = iota

b

c)

例子2:

const (

a = iota //0

b //1

c //2

d = "ha" //独立值,iota += 1

e //"ha" iota += 1

f = 100 //iota +=1

g //100 iota +=1

h = iota //7,恢复计数

i //8

)

算术运算符:

下表列出了所有Go语言的算术运算符。假定 A 值为 10,B 值为 20。

+

相加

A + B 输出结果 30

-

相减

A - B 输出结果 -10

*

相乘

A * B 输出结果 200

/

相除

B / A 输出结果 2

%

求余

B % A 输出结果 0

++

自增

A++ 输出结果 11

--

自减

A-- 输出结果 9

关系运算符:

假定 A 值为 10,B 值为 20。

==

检查两个值是否相等,如果相等返回 True 否则返回 False。

(A == B) 为 False

!=

检查两个值是否不相等,如果不相等返回 True 否则返回 False。

(A != B) 为 True

>

检查左边值是否大于右边值,如果是返回 True 否则返回 False。

(A > B) 为 False

<

检查左边值是否小于右边值,如果是返回 True 否则返回 False。

(A < B) 为 True

>=

检查左边值是否大于等于右边值,如果是返回 True 否则返回 False。

(A >= B) 为 False

<=

检查左边值是否小于等于右边值,如果是返回 True 否则返回 False。

逻辑运算符:

假定 A 值为 True,B 值为 False

&&

逻辑 AND 运算符。 如果两边的操作数都是 True,则条件 True,否则为 False。

(A && B) 为 False

||

逻辑 OR 运算符。 如果两边的操作数有一个 True,则条件 True,否则为 False。

(A || B) 为 True

!

逻辑 NOT 运算符。 如果条件为 True,则逻辑 NOT 条件 False,否则为 True。

!(A && B) 为 True

赋值运算符

=

简单的赋值运算符,将一个表达式的值赋给一个左值

C = A + B 将 A + B 表达式结果赋值给 C

+=

相加后再赋值

C += A 等于 C = C + A

-=

相减后再赋值

C -= A 等于 C = C - A

*=

相乘后再赋值

C *= A 等于 C = C * A

/=

相除后再赋值

C /= A 等于 C = C / A

%=

求余后再赋值

C %= A 等于 C = C % A

<<=

左移后赋值

C <<= 2 等于 C = C << 2

>>=

右移后赋值

C >>= 2 等于 C = C >> 2

&=

按位与后赋值

C &= 2 等于 C = C & 2

^=

按位异或后赋值

C ^= 2 等于 C = C ^ 2

|=

按位或后赋值

C |= 2 等于 C = C | 2

语言条件语句

if 语句

if 语句 由一个布尔表达式后紧跟一个或多个语句组成。

if...else 语句

if 语句 后可以使用可选的 else 语句, else 语句中的表达式在布尔表达式为 false 时执行。

if 嵌套语句

你可以在 ifelse if 语句中嵌入一个或多个 ifelse if 语句。

switch 语句

switch 语句用于基于不同条件执行不同动作。

select 语句

select 语句类似于 switch 语句,但是select会随机执行一个可运行的case。如果没有case可运行,它将阻塞,直到有case可运行。

循环语句:

for 循环

重复执行语句块

循环嵌套

在 for 循环中嵌套一个或多个 for 循环

循环控制语句:

break 语句

经常用于中断当前 for 循环或跳出 switch 语句

continue 语句

跳过当前循环的剩余语句,然后继续进行下一轮循环。

goto 语句

将控制转移到被标记的语句。

无限循环:通过 for 循环语句中只设置一个条件表达式来执行无限循环

package main

import "fmt"

func main() {

for true {

fmt.Printf("这是无限循环。\n");

}}

函数定义:

func function_name( [parameter list] (参数类型)) [return_types(返回值类型)] {

函数体

}

实例:

package main

import "fmt"

func main() {

/* 定义局部变量 */

var a int = 100

var b int = 200

var ret int

/* 调用函数并返回最大值 */

ret = max(a, b)

fmt.Printf( "最大值是 : %d\n", ret )}

/* 函数返回两个数的最大值 */

func max(num1, num2 int) int {

/* 定义局部变量 */

var result int

if (num1 > num2) {

result = num1

} else {

result = num2

}

return result }

注意: 在函数内码不能改变用来调用所述函数的参数。考虑函数swap()的定义

Go 函数 局部变量 与 全局变量:

局部变量:

在函数体内声明的变量称之为局部变量,它们的作用域只在函数体内,参数和返回值变量也是局部变量。

package main

import "fmt"

func main() {

/* 声明局部变量 */

var a, b, c int

/* 初始化参数 */

a = 10

b = 20

c = a + b

fmt.Printf ("结果: a = %d, b = %d and c = %d\n", a, b, c)}

全局变量

在函数体外声明的变量称之为全局变量,全局变量可以在整个包甚至外部包(被导出后)使用。

全局变量可以在任何函数中使用,以下实例演示了如何使用全局变量:

package main

import "fmt"

/* 声明全局变量 */

var g int

func main() {

/* 声明局部变量 */

var a, b int

/* 初始化参数 */

a = 10

b = 20

g = a + b

fmt.Printf("结果: a = %d, b = %d and g = %d\n", a, b, g)}

注意: Go 语言程序中全局变量与局部变量名称可以相同,但是函数内的局部变量会被优先考虑

Go 语言数组:

声明数组:

var variable_name [SIZE] variable_type

例子:

package main

import "fmt"

func main() {

var n [10]int /* n 是一个长度为 10 的数组 */

var i,j int

/* 为数组 n 初始化元素 */

for i = 0; i < 10; i++ {

n[i] = i + 100 /* 设置元素为 i + 100 */

}

/* 输出每个数组元素的值 */

for j = 0; j < 10; j++ {

fmt.Printf("Element[%d] = %d\n", j, n[j] )

}}

Go语言结构体:

例:

package main

import "fmt"

type Books struct {

title string

author string

subject string

book_id int}

func main() {

var Book1 Books /* 声明 Book1 为 Books 类型 */

var Book2 Books /* 声明 Book2 为 Books 类型 */

/* book 1 描述 */

Book1.title = "Go 语言"

Book1.author = "www.runoob.com"

Book1.subject = "Go 语言教程"

Book1.book_id = 6495407

/* book 2 描述 */

Book2.title = "Python 教程"

Book2.author = "www.runoob.com"

Book2.subject = "Python 语言教程"

Book2.book_id = 6495700

/* 打印 Book1 信息 */

fmt.Printf( "Book 1 title : %s\n", Book1.title)

fmt.Printf( "Book 1 author : %s\n", Book1.author)

fmt.Printf( "Book 1 subject : %s\n", Book1.subject)

fmt.Printf( "Book 1 book_id : %d\n", Book1.book_id)

/* 打印 Book2 信息 */

fmt.Printf( "Book 2 title : %s\n", Book2.title)

fmt.Printf( "Book 2 author : %s\n", Book2.author)

fmt.Printf( "Book 2 subject : %s\n", Book2.subject)

fmt.Printf( "Book 2 book_id : %d\n", Book2.book_id)

//第二种 结构体作为函数参术

func printBook( book Books ) {

fmt.Printf( "Book title : %s\n", book.title);

fmt.Printf( "Book author : %s\n", book.author);

fmt.Printf( "Book subject : %s\n", book.subject);

fmt.Printf( "Book book_id : %d\n", book.book_id);

}

Go语言切片:

go语言切片是数组的对象.

Go 数组的长度不可改变,在特定场景中这样的集合就不太适用,Go中提供了一种灵活,功能强悍的内置类型切片("动态数组"),与数组相比切片的长度是不固定的,可以追加元素,在追加时可能使切片的容量增大。

定义切片: var identifier []type

切片不需要长度

或者使用make() 函数来创建切片

var slice1 []type = make([]type, len)

也可以简写为

slice1 := make([]type, len)

例: slice2 := make([]int32, 9)

slice3 := []int32{}

len() 和 cap() 函数

切片是可索引的,并且可以由 len() 方法获取长度。

切片提供了计算容量的方法 cap() 可以测量切片最长可以达到多少。

注意:切片的零值为 nil 。对于切片的零值, len 和 cap 都将返回0。

追加使用append()方法 复制使用copy()方法.

实际的是获取数组的某一部分,len切片<=cap切片<=len数组,切片由三部分组成:指向底层数组的指针、len、cap。

Go语言范围:

Go语言中 range 关键字用于for循环迭代数组(array) 切片(slice) 通道(channel) 或者集合(map)的元素, 在数组和切片中返回元素的索引值,在集合中返回key-value 对的key值.

实例:

package mainimport "fmt"

func main() {

//这是我们使用range去求一个slice的和。使用数组跟这个很类似

nums := []int{2, 3, 4}

sum := 0

for _, num := range nums {

sum += num

}

fmt.Println("sum:", sum)

//在数组上使用range将传入index和值两个变量。上面那个例子我们不需要使用该元素的序号,所以我们使用空白符"_"省略了。有时侯我们确实需要知道它的索引。

for i, num := range nums {

if num == 3 {

fmt.Println("index:", i)

}

}

//range也可以用在map的键值对上。

kvs := map[string]string{"a": "apple", "b": "banana"}

for k, v := range kvs {

fmt.Printf("%s -> %s\n", k, v)

}

//range也可以用来枚举Unicode字符串。第一个参数是字符的索引,第二个是字符(Unicode的值)本身。

for i, c := range "go" {

fmt.Println(i, c)

}}

结果:

sum: 9

index: 1

a -> apple

b -> banana0 1031 111

Go语言Map:

Map 是一种无序的键值对的集合。Map 最重要的一点是通过 key 来快速检索数据,key 类似于索引,指向数据的值。 Map 是一种集合,所以我们可以像迭代数组和切片那样迭代它。不过,Map 是无序的,我们无法决定它的返回顺序,这是因为 Map 是使用 hash 表来实现的。

实例:

package main

import "fmt"

func main() {

var countryCapitalMap map[string]string

/* 创建集合 */

countryCapitalMap = make(map[string]string)

/* map 插入 key-value 对,各个国家对应的首都 */

countryCapitalMap["France"] = "Paris"

countryCapitalMap["Italy"] = "Rome"

countryCapitalMap["Japan"] = "Tokyo"

countryCapitalMap["India"] = "New Delhi"

/* 使用 key 输出 map 值 */

for country := range countryCapitalMap {

fmt.Println("Capital of",country,"is",countryCapitalMap[country])

}

/* 查看元素在集合中是否存在 */

captial, ok := countryCapitalMap["United States"]

/* 如果 ok 是 true, 则存在,否则不存在 */

if(ok){

fmt.Println("Capital of United States is", captial)

}else {

fmt.Println("Capital of United States is not present")

}}

Delete 函数: 闪出集合元素 ,参数为map和对应的key

例子:

package main

import "fmt

func main() {

/* 创建 map */

countryCapitalMap := map[string] string {"France":"Paris","Italy":"Rome","Japan":"Tokyo","India":"New Delhi"}

fmt.Println("原始 map")

/* 打印 map */

for country := range countryCapitalMap {

fmt.Println("Capital of",country,"is",countryCapitalMap[country])

}

/* 删除元素 */

delete(countryCapitalMap,"France");

fmt.Println("Entry for France is deleted")

fmt.Println("删除元素后 map")

/* 打印 map */

for country := range countryCapitalMap {

fmt.Println("Capital of",country,"is",countryCapitalMap[country])

}}

Go语言递归调用函数:

递归就是运行过程中调用自己.

例子:

阶乘:

package main

import "fmt"

func Factorial(n uint64)(result uint64) {

if (n > 0) {

result = n * Factorial(n-1)//递归

return result

}

return 1}

func main() {

var i int = 15

fmt.Printf("%d 的阶乘是 %d\n", i, Factorial(uint64(i)))}

菲波那切数列(兔子数列):

package main

import "fmt"

func fibonacci(n int) int {

if n < 2 {

return n

}

return fibonacci(n-2) + fibonacci(n-1)}

func main() {

var i int

for i = 0; i < 10; i++ {

fmt.Printf("%d\t", fibonacci(i))

}}

结果:

0 1 1 2 3 5 8 13 21 34

Go语言类型转化:

例: 将整数型转化为浮点类型;

package main

import "fmt"

func main() {

var sum int = 17

var count int = 5

var mean float32

mean = float32(sum)/float32(count)

fmt.Printf("mean 的值为: %f\n",mean)}

输出结果: 3.400000

Go语言接口:

实现接口中的方法就是实现了 这个接口.

Go 语言提供了另外一种数据类型即接口,它把所有的具有共性的方法定义在一起,任何其他类型只要实现了这些方法就是实现了这个接口

实例:

/* 定义接口 */

type interface_name interface {

method_name1 [return_type]

method_name2 [return_type]

method_name3 [return_type]

...

method_namen [return_type]}

/* 定义结构体 */

type struct_name struct {

/* variables */}

/* 实现接口方法 */

func (struct_name_variable struct_name) method_name1() [return_type] {

/* 方法实现 */}...

func (struct_name_variable struct_name) method_namen() [return_type] {

/* 方法实现*/}

实例:

package main

import (

"fmt")

type Phone interface {

call()}

type NokiaPhone struct {}

func (nokiaPhone NokiaPhone) call() {

fmt.Println("I am Nokia, I can call you!")}

type IPhone struct {}

func (iPhone IPhone) call() {

fmt.Println("I am iPhone, I can call you!")}

func main() {

var phone Phone

phone = new(NokiaPhone)

phone.call()

phone = new(IPhone)

phone.call()

}

在上面的例子中,我们定义了一个接口Phone,接口里面有一个方法call()。然后我们在main函数里面定义了一个Phone类型变量,并分别为之赋值为NokiaPhone和IPhone。然后调用call()方法.

Go语言处理错误:

Go语言通过内置的错误接口提供非常简单的错误处理机制.

Error 类型是一个接口,定义:

type error interface {

Error() string

}

函数通常在最后的返回值中返回错误信息。使用errors.New 可返回一个错误信息:

func Sqrt(f float64) (float64, error) {

if f < 0 {

return 0, errors.New("math: square root of negative number")

}

// 实现}

实例:

package main

import (

"fmt")

// 定义一个 DivideError 结构

type DivideError struct {

dividee int

divider int}

// 实现 `error` 接口

func (de *DivideError) Error() string {

strFormat := `

Cannot proceed, the divider is zero.

dividee: %d

divider: 0

`

return fmt.Sprintf(strFormat, de.dividee)}

// 定义 `int` 类型除法运算的函数

func Divide(varDividee int, varDivider int) (result int, errorMsg string) {

if varDivider == 0 {

dData := DivideError{

dividee: varDividee,

divider: varDivider,

}

errorMsg = dData.Error()

return

} else {

return varDividee / varDivider, ""

}

}

func main() {

// 正常情况

if result, errorMsg := Divide(100, 10); errorMsg == "" {

fmt.Println("100/10 = ", result)

}

// 当被除数为零的时候会返回错误信息

if _, errorMsg := Divide(100, 0); errorMsg != "" {

fmt.Println("errorMsg is: ", errorMsg)

}

}