Go语言教程(一看就会)

打印 上一主题 下一主题

主题 975|帖子 975|积分 2925

 

   全篇文章 7000 字左右, 建议阅读时长 1h 以上。  
  

Go语言是一门开源的编程语言,目的在于降低构建简单、可靠、高效软件的门槛。Go平衡了底层系统语言的能力,以及在当代语言中所见到的高级特性。它是快速的、静态类型编译语言。
第一个GO程序

  1. package main // 程序组织成包 (1)
  2. import "fmt" // 格式化输出数据 (2)
  3. // 主函数入口 (3)
  4. func main() {
  5.     fmt.Println("你好世界") // 输出语句 (4)
  6. }
复制代码
逐行解析这个程序


  • (1) 这里是每个go文件必备的,如果当前文件是独立实行必须要利用 package main
  • (2) 引入了一个名为 fmt 的库包。
  • (3) 当go程序实行时,首先调用的就是main.main()函数
  • (4) 调用了fmt库中的Println函数,在屏幕中打印字符串信息。
构建和运行Go程序



  • 构建必要在下令行中输入 go build 文件名.go, 实行后会生成一个同名的可实行文件。
  • 下令行中输入 ./文件名 即可运行
如果你没有本地的Go语言环境,可以通过浏览器在线方式学习: https://go.dev/play/

一、数据类型

1.1 变量

Go语言是一种静态类型的编程语言。
可以通过 var 声明一个或多个变量
  1. var str = "apple"
复制代码
也可以通过 := 语法来进行初始化变量的简写
  1. str := "apple"
复制代码
以上两种创建方式应用代码如下:
  1. package main
  2. import "fmt"
  3. func main() {
  4.         var a = "saycode" // 字符串
  5.         fmt.Println(a)
  6.         var b, c int = 1, 2 // 整型
  7.         fmt.Println(b, c)
  8.         var d = true         // 布尔型
  9.         fmt.Println(d)
  10.         var e int                // 声明变量类型为 int
  11.         fmt.Println(e)
  12.     // 简化方式
  13.         f := "apple" // 字符串
  14.         fmt.Println(f)
  15.         g := true        // 布尔型
  16.         fmt.Println(g)
  17. }
复制代码
多个var声明可以成组
  1. var (
  2.     x int,
  3.     y bool
  4. )
复制代码
如果涉及到多个变量同类型的环境,可以进行平行赋值。
  1. // 多行
  2. name := "saycode"
  3. age := 10
  4. // 平行
  5. name, age := "saycode", 10
复制代码
特别变量 _(下划线)
对于下划线而言,任何值赋值给它,都会被舍弃。程序将3赋值给b,1进行舍弃。
  1. _, b := 1, 3
复制代码
 1.2 常量

常量是可不变的值,Go语言支持字符、字符串、布尔值和数字值的常量。
利用 const 关键字声明
错误案例
运行当前程序发现报错cannot assign to name (untyped string constant "I Like Go"),也就证实了,常量进行初始化值后,是不可以进行改变的。
  1. package main
  2. import "fmt"
  3. func main() {
  4.     const name := "I Like Go"
  5.     name = "I Like Java"
  6.     fmt.Println(name)
  7. }
复制代码
精确案例
将π作为常量进行声明,接着去盘算出圆的面积。
  1. package main
  2. import "fmt"
  3. const PI = 3.14
  4. func main() {
  5.         // 计算圆的面积
  6.         const r = 2
  7.         const area = PI * r * r
  8.         fmt.Println(area)
  9. }
复制代码
二、格式化输出

2.1 默认方式

如果不确定要用什么,可以直接利用%v (最好利用特定)
  1. fmt.Printf("我今年 %v 岁", 20)
  2. // 我今年 20 岁
  3. fmt.Printf("我叫 %v", "张三")
  4. // 我叫 张三
复制代码
2.2 字符串

当必要特定插入字符串时,可利用 %s
  1. fmt.Printf("我叫 %s", "张三")
复制代码
2.3 十进制整数

当必要特定插入十进制整数时,可利用%d
  1. fmt.Printf("我今年 %d 岁", 10)
  2. // 我今年 10岁
复制代码
2.4 浮点数

当必要插入浮点数时,可利用 %f
.数字f (.2f),含义就是保留小数点后两位
  1. fmt.Printf("我今年 %f 岁", 10.22)
  2. // 我今年 10.220000岁
  3. fmt.Printf("我今年 %.2f 岁", 10.22)
  4. // 我今年 10.22岁
复制代码
2.5 变量类型

当必要查看当前变量类型时,可利用%T
  1. package main
  2. import "fmt"
  3. func main() {
  4.    
  5.         num := 10
  6.         fmt.Printf("num类型为 %T", num)
  7. }
复制代码
三、控制结构

3.1 条件判定if

if语句是一种用于判定条件的结构,他将根据布尔表达式,效果就是 (true 或 false)的效果来决定是否实行某段代码。
else 是不满足前一个 if 后去实行的代码块。
如下代码就是判定 x > 5(布尔表达式), 如果大于则实行"x大于5",否则实行 "x小于或等于5"
  1. if x > 5 {
  2.     fmt.Println("x大于5")
  3. } else {
  4.     fmt.Println("x小于或等于5")
  5. }
复制代码
3.2 if的嵌套

可以通过嵌套的方式去判定多个值
  1. if x > 5 {
  2.     fmt.Println("x大于5")
  3. } else if x < 5 {
  4.     fmt.Println("x小于5")
  5. } else {
  6.     fmt.Println("x等于5")
  7. }
复制代码
if语句可以有初始化语句,初始化语句中创建的变量只在if语句块中利用。
以下代码是通过getLength方法去获取email字符串的长度,在去对长度进行判定巨细是否小于1。
  1. package main
  2. import "fmt"
  3. func main() {
  4.         email := "nazhanpeng@163.com"
  5.     // 语法糖创建
  6.         if length := getLength(email); length < 1 {
  7.                 fmt.Println("邮箱长度小于1")
  8.         } else {
  9.                 fmt.Println("邮箱没问题")
  10.         }
  11. }
  12. func getLength(a string) int {
  13.         return len(a)
  14. }
复制代码
3.4 goto

可以利用goto去跳转到当前函数的内定标签位置。例如以下示例。
  1. package main
  2. import "fmt"
  3. func myGoto() {
  4.         i := 1
  5. Position:        // 定义跳转目标标签(注意要以冒号结尾)
  6.         fmt.Println(i)
  7.         i++        // i++ == i+1
  8.         if i == 10 {        // 限制输出10次以内
  9.                 return
  10.         }
  11.         goto Position        // 跳转到目标标签
  12. }
  13. func main() {
  14.         myGoto()
  15. }
复制代码
3.5 for循环

for循环的写法有三种情势
   (1)、for 初始化语句; 条件语句; 后置语句 { } 正常循环
  1. package main
  2. import "fmt"
  3. func main() {
  4.         sum := 0
  5.         for i := 0; i < 10; i++ {
  6.                 sum += i        //  将i的值进行累加
  7.         }
  8.         fmt.Println("sum = ", sum)
  9. }
复制代码
  (2)、for 条件语句 { } 和while一样
  1. package main
  2. import "fmt"
  3. func main() {
  4.         sum, i := 0, 0
  5.         for i < 10 {
  6.                 sum += i
  7.                 i++
  8.         }
  9.         fmt.Println("sum = ", sum)
  10. }
复制代码
  (3)、for { } 死循环
  1. package main
  2. import "fmt"
  3. func main() {
  4.         for {
  5.         fmt.Println("我爱学 Go")
  6.     }
  7. }
复制代码
3.6 break

利用break可以终止当前语句的实行。下面循环打印了0-5。
  1. package main
  2. import "fmt"
  3. func main() {
  4.         for i := 0; i < 10; i++ {
  5.                 if i > 5 {
  6.                         break // 终止当前循环
  7.                 }
  8.                 fmt.Println("i=", i)
  9.         }
  10. }
复制代码
3.7 continue

可以让循环进入下一次迭代,也就是跳过当前这一次的循环。下面循环打印了0-9,但是当i=5时,跳过了。
  1. package main
  2. import "fmt"
  3. func main() {
  4.         for i := 0; i < 10; i++ {
  5.                 if i == 5 {
  6.                         continue
  7.                 }
  8.                 fmt.Println("i=", i)
  9.         }
  10. }
复制代码
3.8 switch

从上到下去实行switch的代码块,直到找到匹配项,如果switch没有表达式,会去匹配true。
  1. package main
  2. import "fmt"
  3. func main() {
  4.         i := 1
  5.         switch i {        // 检测i的值是否有匹配项
  6.         case 0:        // case 值,为匹配项
  7.                 fmt.Println("i=0")
  8.         case 1:
  9.                 fmt.Println("i=1")
  10.         }
  11. }
复制代码
当我进行匹配时,想让它向下进行匹配时,必要用到 fallthroungh 关键字。下面当i=0时,会自定向下匹配,去实行对应语句。
  1. package main
  2. import "fmt"
  3. func main() {
  4.         i := 0
  5.         switch i {
  6.         case 0:
  7.                 fallthrough
  8.         case 1:
  9.                 fmt.Println("寻找到了", i)
  10.         }
  11. }
复制代码
我们也可以去指定当没有任何匹配项时的默认行为,利用 default 关键字。下面当i=2时,会默认去实行默认行为。
  1. package main
  2. import "fmt"
  3. func main() {
  4.         i := 2
  5.         switch i {
  6.         case 0:
  7.                 fallthrough
  8.         case 1:
  9.                 fmt.Println("寻找到", i)
  10.         default:        // 如果i不等于0和1,则默认执行
  11.                 fmt.Println("默认执行")
  12.         }
  13. }
复制代码
也可以在一个case中匹配匹配多个值,利用逗号进行分隔。下面将1-5的数字进行分隔。
  1. package main
  2. import "fmt"
  3. func main() {
  4.         i := 1
  5.         switch i {
  6.         case 1, 2, 3, 4, 5: // 逗号相当于 或,也就是 1 或 2 或 3 或 4 或 5
  7.                 fmt.Println("i=", i)
  8.         }
  9. }
复制代码

四、数组

数组是一种固定长度、同类型元素的集合。数组的长度在声明时就被确定,而且无法改变。
4.1 创建数组

   var 数组名 [数组长度]数组类型
  1. var nums [5]int
  2. var names [3]string
复制代码
4.2 数组初始化

可以在声明数组的同时去进行初始化
  1. nums := [5]int{1, 2, 3, 4, 5}
  2. names := [3]string{"张三", "李四", "王五"}
复制代码
对于数组长度可以利用省略号来进行替换,这样编译器会通过初始化值的数量去判定数组的长度。
  1. nums := [...]int{1, 2, 3, 4, 5}
复制代码
对于访问数组元素,可以通过数组下标来进行访问。 数组下标都是以0开始。下面有一个整数数组1到5。它的下标值是这样的。


下面声明一个1到5元素的数组,对数组元素进行访问。
  1. package main
  2. import "fmt"
  3. func main() {
  4.         arr := [5]int{1, 2, 3, 4, 5} // 声明数组
  5.         fmt.Println("arr[0]=", arr[0]) // 访问下标0位置的元素
  6.         fmt.Println("arr[2]=", arr[2]) // 访问下标2位置的元素
  7. }
复制代码
4.3 遍历数组的两种方式

   (1)、通过for循环进行遍历数组。
  1. package main
  2. import "fmt"
  3. func main() {
  4.         nums := [...]int{1, 2, 3, 4, 5}
  5.         for i := 0; i < len(nums); i++ {
  6.                 fmt.Println(nums[i])
  7.         }
  8. }
复制代码
  (2)、通过for循环进行遍历数组。 
  range 是一个迭代器,利用时会在循环的内容中返回一个键值对。下面是一个range循环的一个写法, k是键,v是值。range背面紧接着遍历数据
   for k, v := range slice/array/string/map/channel { }
  下面是利用range 去遍历一个nums 的一个数组的例子。
  1. package main
  2. import "fmt"
  3. func main() {
  4.         nums := [...]int{1, 2, 3, 4, 5}
  5.         for index, value := range nums {
  6.                 fmt.Printf("索引: %d, 值: %d\n", index, value)
  7.         }
  8. }
复制代码
4.4 声明多维数组

   var 数组名 [数组长度][数组长度]数组类型
  1. var nums [3][4]int // 声明一个 3*4的二维整数型数组
复制代码
可以在声明多维数组时,直接进行初始化。
  1. package main
  2. import "fmt"
  3. func main() {
  4.         nums := [3][4]int{
  5.                 {1, 2, 3, 4},
  6.                 {5, 6, 7, 8},
  7.                 {9, 10, 11, 12},
  8.         }
  9.         fmt.Println(nums)
  10. }
复制代码
初始化后的样子如下。


当我们对部门值进行初始化,未被初始化的位置将被赋值为0。
  1. package main
  2. import "fmt"
  3. func main() {
  4.         nums := [3][4]int{
  5.                 {1, 2},
  6.                 {5, 6, 7},
  7.         }
  8.         fmt.Println(nums)
  9. }
复制代码
初始化后的样子如下。


4.5 访问和修改多维数组

可以通过索引访问和修改多维数组的元素。
  1. package main
  2. import "fmt"
  3. func main() {
  4.         nums := [3][4]int{
  5.                 {1, 2, 3, 4},
  6.                 {5, 6, 7, 8},
  7.                 {9, 10, 11, 12},
  8.         }
  9.         fmt.Println(nums)
  10.         nums[1][2] = 10
  11.         fmt.Println(nums[1][2])
  12. }
复制代码
对于遍历多维数组,可以利用for循环嵌套来进行遍历。下面程序中i代表的是多维数组的行,j代表的是多维数组的列,也就是多维数组要是用两个下标才可以进行访问。
  1. package main
  2. import "fmt"
  3. func main() {
  4.         nums := [3][4]int{
  5.                 {1, 2, 3, 4},
  6.                 {5, 6, 7, 8},
  7.                 {9, 10, 11, 12},
  8.         }
  9.         for i := 0; i < len(nums); i++ {
  10.                 for j := 0; j < len(nums[i]); j++ {
  11.                         fmt.Printf("nums[%d][%d]=%d\n", i, j, nums[i][j])
  12.                 }
  13.         }
  14. }
复制代码
上面程序中nums数组的下标值如下。


五、slice

动态数组(slice)是对数组的抽象。它可以改变长度和容量,并能共享底层数组的数据。
5.1 创建slice

  1. var s []int // 声明一个整数类型的 动态数组
复制代码
从另一个数组中创建动态数组
  1. arr := [5]int{1, 2, 3, 4, 5}
  2. s := arr[1:4] // 创建一个包含 arr中从索引1到索引3元素的动态数组
  3. s2 := s[1:2] // 创建一个基于s的动态数组
复制代码
5.2 make函数

可以利用内置 make 函数来创建一个指定长度和容量的slice。下面所说的长度为5,容量为10,是说会创建可以容纳10个的slice,默认插入5个为0的整数。
  1. package main
  2. import "fmt"
  3. func main() {
  4.         s1 := make([]int, 5) // 长度为5的整数。
  5.         s2 := make([]int, 5, 10) // 长度为5,容量为10的整数。
  6.         fmt.Println(s1)
  7.         fmt.Println(s2)
  8. }
复制代码
也可以通过字面量的方式去进行初始化。
  1. s := []int{1, 2, 3, 4, 5}
复制代码
5.3 len函数与cap函数

假设我们创建了一个slice,可以通过len函数和cap函数来获取对应的长度和容量。
  1. package main
  2. import "fmt"
  3. func main() {
  4.         s := []int{1, 2, 3, 4, 5}
  5.         fmt.Println("长度: ", len(s)) // 5
  6.         fmt.Println("容量: ", cap(s)) // 5
  7. }
复制代码
5.4 追加元素

通过利用内容函数 append向slice内追加元素,而且会返回追加后的slice
   var 数组名 [数组长度][数组长度]数组类型
  1. package main
  2. import "fmt"
  3. func main() {
  4.     s := []int{1, 2, 3, 4, 5}
  5.     s = append(s, 4, 5)
  6.     fmt.Println(s) // [1 2 3 4 5]
  7. }
复制代码
如果被追加的slice 没有足够的容量去存储追加的元素,append 会分配一个足够大的slice来存放原有slice和追加的元素。
  1. package main
  2. import "fmt"
  3. func main() {
  4.     s0 := []int{0, 1}
  5.     s1 := append(s0, 2) // 追加一个元素2, [0 0 2]
  6.     s2 := append(s1, 3) // 追加一个元素3, [0 0 2 3]
  7. }
复制代码
5.5 copy函数

copy函数可以从slice中复制元素到新的slice。会返回复制的元素的个数。
  1. package main
  2. import "fmt"
  3. func main() {
  4.         var a = [...]int{0, 1, 2, 3, 4, 5}
  5.         var s = make([]int, 4)
  6.         l1 := copy(s, a[0:]) // 从slice 0开始复制并存储到s中, [0 1 2 3]
  7.         fmt.Println(s)
  8.         fmt.Println("l1=", l1)
  9.         l2 := copy(s, s[2:]) // 从slice 2开始复制并存储到s中, [2 3 2 3]
  10.         fmt.Println(s)
  11.         fmt.Println("l2=", l2)
  12. }
复制代码
5.6 遍历 slice

可以利用for循环进行遍历
  1. package main
  2. import "fmt"
  3. func main() {
  4.     s := []int{1, 2, 3, 4, 5}
  5.     for i := 0; i < len(s); i++ {
  6.         fmt.Println(s[i)
  7.     }
  8. }
复制代码
也可以利用for range循环遍历
  1. package main
  2. import "fmt"
  3. func main() {
  4.     s := []int{1, 2, 3, 4, 5}
  5.     for index, value := range s {
  6.         fmt.Printf("索引: %d, 值: %d\n", index, value)
  7.     }
  8. }
复制代码
六、函数

一个基本的函数必要包罗函数名、参数列表、返回值类型和函数体。
例如界说一个函数名为add的函数,包罗两个参数a、b,返回值类型为int类型,函数体是a+b盘算两个整数的和。
  1. func add(a int, b int) int {
  2.     return a + b
  3. }
复制代码
函数可以有0个或多个参数。
4.1 返回效果

一般用于去终止函数并返回效果。在Go中可以返回单个值或多个值。
单个值返回已经在上面返回了。
4.1.1 多个值返回

  1. package main
  2. import "fmt"
  3. func divide(a int, b int) (int, int) {
  4.     quotient := a / b
  5.     remainder := a % b
  6.     return quotient, remainder
  7. }
  8. func main() {
  9.     q, r := divide(4, 3)
  10.     fmt.Println(q,r)
  11. }
复制代码
4.1.2 定名返回值

定名返回值在函数代码块内为局部变量,可以进行利用。
  1. package main
  2. import "fmt"
  3. func rectangleArea(width, height int) (area int) {
  4.     area = width * height
  5.     return
  6. }
  7. func main() {
  8.     area := rectangleArea(5,6)
  9.     fmt.Println("area", area)
  10. }
复制代码
4.1.3 空返回语句

可以利用空return返回效果
  1. package main
  2. import "fmt"
  3. func swap(a, b int) (x, y int) {
  4.     x = b
  5.     y = a
  6.     return
  7. }
  8. func main() {
  9.     x, y := swap(1,2)
  10.     fmt.Println("x", y, "y", y)
  11. }
复制代码
4.1.4 按照值传递变量

意味着当一个变量传递给一个函数时,该函数收到的是该变量的副本。
我们发现x的值还是5,就说明函数无法去改变传递变量的值。
  1. package main
  2. import "fmt"
  3. func main() {
  4.         x := 5
  5.         increment(x)
  6.         fmt.Println("x=", x)
  7. }
  8. func increment(x int) {
  9.         x++
  10. }
复制代码
明天继承更新,请关注我


免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

水军大提督

金牌会员
这个人很懒什么都没写!
快速回复 返回顶部 返回列表