教程网址:https://www.runoob.com/go/go-tutorial.html
Go 语言语法与 C 相近,有C的基础的话入门很简单。下面的笔记直接去掉了跟C语言重叠的部分规则。
文章目录
Go语言教程
第一个 Go 程序 hello.go(Go 语言源文件的扩展是 .go),代码如下:
package main
import "fmt"
func main() {
fmt.Println("Hello, World!")
}
注意 { 不能单独放一行
运行go程序的命令
go run hello.go
也可以先build后运行
go bulid hello.go #编译生成二进制文件hello
./hello #运行二进制文件
Go 语言结构
- package main 定义了包名。你必须在源文件中非注释的第一行指明这个文件属于哪个包,如:package main。package main表示一个可独立执行的程序,每个 Go 应用程序都包含一个名为 main 的包。
- import "fmt" 引入fmt 包,fmt 包实现了格式化 IO(输入/输出)的函数。
- func main() 是程序开始执行的函数。每一个可执行程序所必须包含main 函数,一般来说都是在启动后第一个执行的函数(如果有 init() 函数则会先执行该函数)。
- 注释方式跟C/C++相同,用 // 或 /*… */
- fmt.Println(…) 输出字符串,并在最后自动增加换行字符 \n,等同于fmt.Print(“hello, world\n”)
- 以一个大写字母开头的标识符(包括常量、变量、类型、函数名、结构字段等等)对象,如:Group1可以被外部包的代码所使用(客户端程序需要先导入这个包),这被称为导出(像面向对象语言中的 public);标识符如果以小写字母开头,则对包外是不可见的,只能在包内使用(像面向对象语言中的 protected )。
Go 语言基础语法
与C/C++基本相同,建议多用空格使语句更美观。
Go 语言数据类型
与C/C++一样,在 Go 编程语言中,数据类型用于声明函数和变量。数据类型的出现是为了把数据分成所需内存大小不同的数据,编程的时候需要用大数据的时候才需要申请大内存,就可以充分利用内存。
布尔型bool、整型 int 和浮点型 float32、float64 等等。
Go 语言变量
-
声明变量时指定变量类型
var identifier type //声明一个type类型的变量identifier identifier = value //给变量赋值 var a string = "Runoob" var identifier1, identifier2 type //声明两个type类型的变量identifier1、identifier2 var b, c int = 1, 2
-
声明变量时不给定变量类型,让编译器根据值自行判定变量类型
var v_name = value var b = true
-
极致偷懒:声明变量时不仅不给定变量类型,还把var省略掉
v_name := value a := 1 //注意使用:=时左边必须声明新的变量,不能用来给已声明的变量赋值 s := "fight"
看起来的话使用这种方法最简洁,但是它只能用在函数体中,用来声明局部变量,不能用来声明全局变量。声明全局变量还是得用前面两种。
声明了一个局部变量却没有在相同的代码块中使用它,会得到编译错误。而全局变量是允许声明但不使用。
go语言允许并行赋值,也就是类似 var b , c = 1 , true
,因此go函数可以返回多个返回值(像python一样)。
Go 语言常量
常量是指不会被改变的量。
const b string = "abc" //显式类型定义
const b = "abc" //隐式类型定义
const ( //枚举
Unknown = 0
Female = 1
Male = 2
)
iota,特殊常量,可以认为是一个可以被编译器修改的常量。iota 在 const关键字出现时将被重置为 0(const 内部的第一行之前),const 中每新增一行常量声明将使 iota 计数一次(iota 可理解为 const 语句块中的行索引)。
Go 语言运算符&条件语句
跟C/C++一模一样
Go 语言循环语句
for循环有三种形式:
for init; condition; post { }
for condition { } //跟while一样
for { } //无限循环
举实例代码是最简洁明了的。
for 循环的 range 格式可以对 slice、map、数组、字符串等进行迭代循环。格式如下:
for key, value := range oldMap {
newMap[key] = value
}
计算1~10的数字之和
package main
import "fmt"
func main() {
sum := 0
for i := 0; i <= 10; i++ {
sum += i
}
fmt.Println(sum)
}
For-each range 循环
这种格式的循环可以对字符串、数组、切片等进行迭代输出元素。
package main
import "fmt"
func main() {
strings := []string{"google", "runoob"}
for i, s := range strings {
fmt.Println(i, s)
}
numbers := [6]int{1, 2, 3, 5}
for i,x:= range numbers {
fmt.Printf("第 %d 位 x 的值 = %d\n", i,x)
}
}
Go 语言函数
Go 语言函数定义格式如下:
func function_name( [parameter list] ) [return_types] {
函数体
}
实例
/* 函数返回两个数的最大值 */
func max(num1, num2 int) int { //传参时不用写var
/* 声明局部变量 */
var result int
if (num1 > num2) {
result = num1
} else {
result = num2
}
return result
}
上述的是值传递,下面的是引用传递
/* 定义交换值函数*/
func swap(x *int, y *int) {
var temp int
temp = *x /* 保持 x 地址上的值 */
*x = *y /* 将 y 值赋给 x */
*y = temp /* 将 temp 值赋给 y */
}
Go 语言变量作用域
跟C/C++一模一样
Go 语言数组
Go 语言数组声明需要指定元素类型及元素个数,语法格式如下:
var variable_name [SIZE] variable_type
以上为一维数组的定义方式。例如以下定义了数组 balance 长度为 10 类型为 float32:
var balance [10] float32 //[]中必须填数字
数组初始化:
var balance = [5]float32{1000.0, 2.0, 3.4, 7.0, 50.0} //初始化[]中可以不填数字,让编译器自行判断
访问数组元素
var salary float32 = balance[3]
向函数传递数组
func getAverage(arr []int, size int) float32
{
var i int
var avg, sum float32
for i = 0; i < size; ++i {
sum += arr[i]
}
avg = sum / size
return avg;
}
Go 语言指针
一个指针变量指向了一个值的内存地址。
以下是有效的指针声明(都是空指针 nil ):
var ip *int /* 指向整型*/
var fp *float32 /* 指向浮点型 */
指针使用流程:
- 定义指针变量。
- 为指针变量赋值。
- 访问指针变量中指向地址的值。
package main
import "fmt"
func main() {
var a int= 20 /* 声明实际变量 */
var ip *int /* 声明指针变量 */
ip = &a /* 指针变量的存储地址 */
fmt.Printf("a 变量的地址是: %x\n", &a )
fmt.Printf("ip 变量储存的指针地址: %x\n", ip ) /* 指针变量的存储地址 */
fmt.Printf("*ip 变量的值: %d\n", *ip ) /* 使用指针访问值 */
}
Go 语言结构体
直接上实例
package main
import "fmt"
type Books struct {
title string
author string
subject string
book_id int
}
func main() {
var Book1 Books /* 声明 Book1 为 Books 类型 */
/* book 1 描述 */
Book1.title = "Go 语言"
Book1.author = "www.runoob.com"
Book1.subject = "Go 语言教程"
Book1.book_id = 6495407
// 创建一个新的结构体
var Book2 Books = Books{"Go 语言", "www.runoob.com", "Go 语言教程", 6495407}
// 也可以使用 key => value 格式 , 忽略的字段为 0 或 空
var Book3 Books = Books{title: "Go 语言", author: "www.runoob.com"}
}
访问结构体成员也是跟C/C++一样
结构体.成员名"
你可以定义指向结构体的指针类似于其他指针变量,格式如下:
var book_pointer *Books
以上定义的指针变量可以存储结构体变量的地址。查看结构体变量地址,可以将 & 符号放置于结构体变量前:
book_pointer = &Book1
使用结构体指针访问结构体成员,使用 “.” 操作符:
book_pointer.title
那这跟Book1.title好像一样啊,似乎是没什么意义。
Go 语言切片(Slice)
与数组相比切片的长度是不固定的,可以追加元素,在追加时可能使切片的容量增大。
你可以声明一个未指定大小的数组来定义切片:
var identifier []type
或使用make()函数来创建切片:
var slice1 []type = make([]type, len) //len是切片的初始长度
slice1 := make([]type, len) //简写版本
切片初始化
s :=[] int {1,2,3 } //[]表示是切片类型,{1,2,3}初始化值依次是1,2,3.其cap=len=3
s := arr[startIndex:endIndex] //将数组arr中从下标startIndex到endIndex-1 的元素创建为一个新的切片
len() 方法获取切片长度:len(s)
截取部分切片,类似python,比如 s[1:3] 代表第二个元素到第三个元素(注意包括索引下限的元素,不包括索引上限的元素)。
拷贝切片的 copy 方法和向切片追加新元素的 append 方法
package main
import "fmt"
func main() {
var numbers []int
numbers = append(numbers, 1) /* 向切片添加一个元素 */
/* 创建切片 numbers1 是之前切片的两倍容量*/
numbers1 := make([]int, len(numbers), (cap(numbers))*2)
copy(numbers1,numbers)/* 拷贝 numbers 的内容到 numbers1 */
}
Go 语言范围(Range)
Go 语言中 range 关键字用于 for 循环中迭代数组(array)、切片(slice)、通道(channel)或集合(map)的元素。在数组和切片中它返回元素的索引和索引对应的值,在集合中返回 key-value 对。
package main
import "fmt"
func main() {
//这是我们使用range去求一个slice的和。使用数组跟这个很类似
nums := []int{2, 3, 4}
sum := 0
for _, num := range nums {
sum += num
}
//在数组上使用range将传入index和值两个变量。上面那个例子我们不需要使用该元素的序号,所以我们使用空白符"_"省略了。
//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)
}
}
Go 语言Map(集合)
Map 是一种无序的键值对的集合。Map 最重要的一点是通过 key 来快速检索数据,可以像迭代数组和切片那样迭代它。不过Map 是无序的,无法决定它的返回顺序,这是因为 Map 是使用 hash 表来实现的。
定义map
/* 声明变量,默认 map 是 nil ,没有初始化,不能用来存放键值对*/
var map_variable map[key_data_type]value_data_type
/* 使用 make 函数初始化map */
map_variable := make(map[key_data_type]value_data_type)
如果不初始化 map,那么就会创建一个 nil map。nil map 不能用来存放键值对
package main
import "fmt"
func main() {
countryCapitalMap := make(map[string]string)/*创建集合 */
/* map插入key - value对,各个国家对应的首都 */
countryCapitalMap [ "France" ] = "巴黎"
countryCapitalMap [ "Italy" ] = "罗马"
/*使用键输出地图值 */
for country := range countryCapitalMap {
fmt.Println(country, "首都是", countryCapitalMap [country])
}
/*查看元素在集合中是否存在 */
capital, ok := countryCapitalMap [ "American" ]
if (ok) {
fmt.Println("American 的首都是", capital)
} else {
fmt.Println("American 的首都不存在")
}
}
Go 语言递归函数
十分简单,与C/C++相同
Go 语言类型转换
十分简单,也跟C/C++一样
var num_int int = 5
var num_float32 float32
num_float32=float32(num_int)