Go语言教程(一看就会)

 

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

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

第一个GO程序

package main // 程序组织成包 (1)import "fmt" // 格式化输出数据 (2)// 主函数入口 (3)
func main() {fmt.Println("你好世界") // 输出语句 (4)
}

逐行解析这个程序

  • (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 声明一个或多个变量

var str = "apple"

也可以通过 := 语法来进行初始化变量的简写

str := "apple"

以上两种创建方式应用代码如下:

package mainimport "fmt"func main() {var a = "saycode" // 字符串fmt.Println(a)var b, c int = 1, 2 // 整型fmt.Println(b, c)var d = true 	// 布尔型fmt.Println(d)var e int		// 声明变量类型为 intfmt.Println(e)// 简化方式f := "apple" // 字符串fmt.Println(f)g := true	// 布尔型fmt.Println(g)
}

多个var声明可以成组

var (x int,y bool
)

如果涉及到多个变量同类型的情况,可以进行平行赋值。

// 多行
name := "saycode"
age := 10// 平行
name, age := "saycode", 10

特殊变量 _(下划线)

对于下划线而言,任何值赋值给它,都会被舍弃。程序将3赋值给b,1进行舍弃。

_, b := 1, 3

 1.2 常量

常量是可不变的值,Go语言支持字符、字符串、布尔值和数字值的常量。

使用 const 关键字声明

错误案例

运行当前程序发现报错cannot assign to name (untyped string constant "I Like Go"),也就证实了,常量进行初始化值后,是不可以进行改变的。

package mainimport "fmt"func main() {const name := "I Like Go"name = "I Like Java"fmt.Println(name)
}

正确案例

将π作为常量进行声明,接着去计算出圆的面积。

package mainimport "fmt"const PI = 3.14func main() {// 计算圆的面积const r = 2const area = PI * r * rfmt.Println(area)
}

二、格式化输出

2.1 默认方式

如果不确定要用什么,可以直接使用%v (最好使用特定)

fmt.Printf("我今年 %v 岁", 20)
// 我今年 20 岁
fmt.Printf("我叫 %v", "张三")
// 我叫 张三

2.2 字符串

当需要特定插入字符串时,可使用 %s

fmt.Printf("我叫 %s", "张三")

2.3 十进制整数

当需要特定插入十进制整数时,可使用%d

fmt.Printf("我今年 %d 岁", 10)
// 我今年 10岁

2.4 浮点数

当需要插入浮点数时,可使用 %f

.数字f (.2f),含义就是保留小数点后两位

fmt.Printf("我今年 %f 岁", 10.22)
// 我今年 10.220000岁
fmt.Printf("我今年 %.2f 岁", 10.22)
// 我今年 10.22岁

2.5 变量类型

当需要查看当前变量类型时,可使用%T

package mainimport "fmt"func main() {num := 10fmt.Printf("num类型为 %T", num)
}

三、控制结构

3.1 条件判断if

if语句是一种用于判断条件的结构,他将根据布尔表达式,结果就是 (true 或 false)的结果来决定是否执行某段代码。

else 是不满足前一个 if 后去执行的代码块。

如下代码就是判断 x > 5(布尔表达式), 如果大于则执行"x大于5",否则执行 "x小于或等于5"

if x > 5 {fmt.Println("x大于5")
} else {fmt.Println("x小于或等于5")
}

3.2 if的嵌套

可以通过嵌套的方式去判断多个值

if x > 5 {fmt.Println("x大于5") 
} else if x < 5 {fmt.Println("x小于5")
} else {fmt.Println("x等于5")
}

if语句可以有初始化语句,初始化语句中创建的变量只在if语句块中使用。

以下代码是通过getLength方法去获取email字符串的长度,在去对长度进行判断大小是否小于1。

package mainimport "fmt"func main() {email := "nazhanpeng@163.com"// 语法糖创建if length := getLength(email); length < 1 {fmt.Println("邮箱长度小于1")} else {fmt.Println("邮箱没问题")}}func getLength(a string) int {return len(a)
}

3.4 goto

可以使用goto去跳转到当前函数的内定标签位置。例如以下示例。

package mainimport "fmt"func myGoto() {i := 1
Position:	// 定义跳转目标标签(注意要以冒号结尾)fmt.Println(i)i++	// i++ == i+1if i == 10 {	// 限制输出10次以内return}goto Position	// 跳转到目标标签
}func main() {myGoto()
}

3.5 for循环

for循环的写法有三种形式

(1)、for 初始化语句; 条件语句; 后置语句 { } 正常循环

package mainimport "fmt"func main() {sum := 0for i := 0; i < 10; i++ {sum += i	//  将i的值进行累加}fmt.Println("sum = ", sum)
}

(2)、for 条件语句 { } 和while一样

package mainimport "fmt"func main() {sum, i := 0, 0for i < 10 {sum += ii++}fmt.Println("sum = ", sum)}

(3)、for { } 死循环

package mainimport "fmt"func main() {for {fmt.Println("我爱学 Go")}
}

3.6 break

利用break可以终止当前语句的执行。下面循环打印了0-5。

package mainimport "fmt"func main() {for i := 0; i < 10; i++ {if i > 5 {break // 终止当前循环}fmt.Println("i=", i)}
}

3.7 continue

可以让循环进入下一次迭代,也就是跳过当前这一次的循环。下面循环打印了0-9,但是当i=5时,跳过了。

package mainimport "fmt"func main() {for i := 0; i < 10; i++ {if i == 5 {continue}fmt.Println("i=", i)}
}

3.8 switch

从上到下去执行switch的代码块,直到找到匹配项,如果switch没有表达式,会去匹配true。

package mainimport "fmt"func main() {i := 1switch i {	// 检测i的值是否有匹配项case 0:	// case 值,为匹配项fmt.Println("i=0")case 1:fmt.Println("i=1")}
}

当我进行匹配时,想让它向下进行匹配时,需要用到 fallthroungh 关键字。下面当i=0时,会自定向下匹配,去执行对应语句。

package mainimport "fmt"func main() {i := 0switch i {case 0:fallthroughcase 1:fmt.Println("寻找到了", i)}
}

我们也可以去指定当没有任何匹配项时的默认行为,使用 default 关键字。下面当i=2时,会默认去执行默认行为。

package mainimport "fmt"func main() {i := 2switch i {case 0:fallthroughcase 1:fmt.Println("寻找到", i)default:	// 如果i不等于0和1,则默认执行fmt.Println("默认执行")}
}

也可以在一个case中匹配匹配多个值,使用逗号进行分隔。下面将1-5的数字进行分隔。

package mainimport "fmt"func main() {i := 1switch i {case 1, 2, 3, 4, 5: // 逗号相当于 或,也就是 1 或 2 或 3 或 4 或 5fmt.Println("i=", i)}
}

四、数组

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

4.1 创建数组

var 数组名 [数组长度]数组类型

var nums [5]int
var names [3]string

4.2 数组初始化

可以在声明数组的同时去进行初始化

nums := [5]int{1, 2, 3, 4, 5}
names := [3]string{"张三", "李四", "王五"}

对于数组长度可以使用省略号来进行替换,这样编译器会通过初始化值的数量去判断数组的长度。

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

对于访问数组元素,可以通过数组下标来进行访问。 数组下标都是以0开始。下面有一个整数数组1到5。它的下标值是这样的。

下面声明一个1到5元素的数组,对数组元素进行访问。

package mainimport "fmt"func main() {arr := [5]int{1, 2, 3, 4, 5} // 声明数组fmt.Println("arr[0]=", arr[0]) // 访问下标0位置的元素fmt.Println("arr[2]=", arr[2]) // 访问下标2位置的元素
}

4.3 遍历数组的两种方式

(1)、通过for循环进行遍历数组。

package mainimport "fmt"func main() {nums := [...]int{1, 2, 3, 4, 5}for i := 0; i < len(nums); i++ {fmt.Println(nums[i])}
}

(2)、通过for循环进行遍历数组。 

range 是一个迭代器,使用时会在循环的内容中返回一个键值对。下面是一个range循环的一个写法, k是键,v是值。range后面紧接着遍历数据

for k, v := range slice/array/string/map/channel { }

下面是使用range 去遍历一个nums 的一个数组的例子。

package mainimport "fmt"func main() {nums := [...]int{1, 2, 3, 4, 5}for index, value := range nums {fmt.Printf("索引: %d, 值: %d\n", index, value)}
}

4.4 声明多维数组

var 数组名 [数组长度][数组长度]数组类型

var nums [3][4]int // 声明一个 3*4的二维整数型数组

可以在声明多维数组时,直接进行初始化。

package mainimport "fmt"func main() {nums := [3][4]int{{1, 2, 3, 4},{5, 6, 7, 8},{9, 10, 11, 12},}fmt.Println(nums)
}

初始化后的样子如下。

当我们对部分值进行初始化,未被初始化的位置将被赋值为0。

package mainimport "fmt"func main() {nums := [3][4]int{{1, 2},{5, 6, 7},}fmt.Println(nums)
}

初始化后的样子如下。

4.5 访问和修改多维数组

可以通过索引访问和修改多维数组的元素。

package mainimport "fmt"func main() {nums := [3][4]int{{1, 2, 3, 4},{5, 6, 7, 8},{9, 10, 11, 12},}fmt.Println(nums)nums[1][2] = 10fmt.Println(nums[1][2])
}

对于遍历多维数组,可以使用for循环嵌套来进行遍历。下面程序中i代表的是多维数组的行,j代表的是多维数组的列,也就是多维数组要是用两个下标才可以进行访问。

package mainimport "fmt"func main() {nums := [3][4]int{{1, 2, 3, 4},{5, 6, 7, 8},{9, 10, 11, 12},}for i := 0; i < len(nums); i++ {for j := 0; j < len(nums[i]); j++ {fmt.Printf("nums[%d][%d]=%d\n", i, j, nums[i][j])}}
}

上面程序中nums数组的下标值如下。

五、slice

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

5.1 创建slice

var s []int // 声明一个整数类型的 动态数组

从另一个数组中创建动态数组

arr := [5]int{1, 2, 3, 4, 5}
s := arr[1:4] // 创建一个包含 arr中从索引1到索引3元素的动态数组s2 := s[1:2] // 创建一个基于s的动态数组

5.2 make函数

可以使用内置 make 函数来创建一个指定长度和容量的slice。下面所说的长度为5,容量为10,是说会创建可以容纳10个的slice,默认插入5个为0的整数。

package mainimport "fmt"func main() {s1 := make([]int, 5) // 长度为5的整数。s2 := make([]int, 5, 10) // 长度为5,容量为10的整数。fmt.Println(s1)fmt.Println(s2)}

也可以通过字面量的方式去进行初始化。

s := []int{1, 2, 3, 4, 5}

5.3 len函数与cap函数

假设我们创建了一个slice,可以通过len函数和cap函数来获取对应的长度和容量。

package mainimport "fmt"func main() {s := []int{1, 2, 3, 4, 5}fmt.Println("长度: ", len(s)) // 5fmt.Println("容量: ", cap(s)) // 5
}

5.4 追加元素

通过使用内容函数 append向slice内追加元素,并且会返回追加后的slice

var 数组名 [数组长度][数组长度]数组类型

package mainimport "fmt"func main() {s := []int{1, 2, 3, 4, 5}s = append(s, 4, 5)fmt.Println(s) // [1 2 3 4 5]
}

如果被追加的slice 没有足够的容量去存储追加的元素,append 会分配一个足够大的slice来存放原有slice和追加的元素。

package mainimport "fmt"func main() {s0 := []int{0, 1}s1 := append(s0, 2) // 追加一个元素2, [0 0 2]s2 := append(s1, 3) // 追加一个元素3, [0 0 2 3]
}

5.5 copy函数

copy函数可以从slice中复制元素到新的slice。会返回复制的元素的个数。

package mainimport "fmt"func main() {var a = [...]int{0, 1, 2, 3, 4, 5}var s = make([]int, 4)l1 := copy(s, a[0:]) // 从slice 0开始复制并存储到s中, [0 1 2 3]fmt.Println(s)fmt.Println("l1=", l1)l2 := copy(s, s[2:]) // 从slice 2开始复制并存储到s中, [2 3 2 3]fmt.Println(s)fmt.Println("l2=", l2)
}

5.6 遍历 slice

可以使用for循环进行遍历

package mainimport "fmt"func main() {s := []int{1, 2, 3, 4, 5}for i := 0; i < len(s); i++ {fmt.Println(s[i)}
}

也可以使用for range循环遍历

package mainimport "fmt"func main() {s := []int{1, 2, 3, 4, 5}for index, value := range s {fmt.Printf("索引: %d, 值: %d\n", index, value)}
}

六、函数

一个基本的函数需要包含函数名、参数列表、返回值类型和函数体。

例如定义一个函数名为add的函数,包含两个参数a、b,返回值类型为int类型,函数体是a+b计算两个整数的和。

func add(a int, b int) int {return a + b
}

函数可以有0个或多个参数。

4.1 返回结果

一般用于去终止函数并返回结果。在Go中可以返回单个值或多个值。

单个值返回已经在上面返回了。

4.1.1 多个值返回

package mainimport "fmt"func divide(a int, b int) (int, int) {quotient := a / bremainder := a % breturn quotient, remainder
}func main() {q, r := divide(4, 3)fmt.Println(q,r)
}

4.1.2 命名返回值

命名返回值在函数代码块内为局部变量,可以进行使用。

package mainimport "fmt"func rectangleArea(width, height int) (area int) {area = width * heightreturn
}func main() {area := rectangleArea(5,6)fmt.Println("area", area)
}

4.1.3 空返回语句

可以使用空return返回结果

package mainimport "fmt"func swap(a, b int) (x, y int) {x = by = areturn
}func main() {x, y := swap(1,2)fmt.Println("x", y, "y", y)
}

4.1.4 按照值传递变量

意味着当一个变量传递给一个函数时,该函数收到的是该变量的副本。

我们发现x的值还是5,就说明函数无法去改变传递变量的值。

package mainimport "fmt"func main() {x := 5increment(x)fmt.Println("x=", x)}func increment(x int) {x++
}

明天继续更新,请关注我

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/385950.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Windows都蓝屏了,你们的SQL真的安全吗?

7月19日&#xff0c;话题“微软蓝屏”冲上了热搜榜第一。微软公司旗下部分应用和服务出现访问延迟、功能不全或无法访问问题&#xff0c;大量用户端电脑出现蓝屏现象。这个技术故障席卷全球&#xff0c;短短两个小时&#xff0c;就造成一场令人措手不及的大规模事件&#xff1a…

MATLAB-bode图编程

num[1 1];den [2 1];tf(num,den)bode(tf(num,den));hold on tf &#xff1a;传递函数 tf&#xff08;x&#xff0c;y&#xff09;&#xff1a;x是分子&#xff0c;y是分母 bode&#xff1a;伯特图 hold on&#xff1a;保持

物理机 gogs+jenkins+sonarqube 实现CI/CD

一、部署gogs_0.11.91_linux_amd64.tar.gz gogs官网下载&#xff1a;https://dl.gogs.io/ yum -y install mariadb-serversystemctl start mariadbsystemctl enable mariadbuseradd gittar zxvf gogs_0.11.91_linux_amd64.tar.gzcd gogsmysql -u root -p < scripts/mysql.…

【C/C++】C语言到C++的入门知识点(主要适用于C语言精通到Qt的C++开发入门)

【C/C】C语言到C的入门知识点&#xff08;主要适用于C语言精通到Qt的C开发入门&#xff09; 文章目录 C语言与C的不同C中写C语言代码C语言到C的知识点Qt开发中需要了解的C基础知识namespace输入输出字符串类型class类构造函数和析构函数&#xff08;解析函数&#xff09;类的继…

【C++】c++语法基础

引入&#xff0c;第一个c程序 这是用c写的helloworld程序 #include<iostream> using namespace std; int main() {cout << "hello,world\n" << endl;return 0;} 接下来我们将根据上述的代码来学习c的基本语法。 命名空间&#xff08;namespace…

基于DoDAF的陆上智能突击系统作战概念系统开发

源自&#xff1a;系统仿真学报 作者&#xff1a;王灿 纪浩然 郭齐胜 董志明 谭亚新 穆歌 注&#xff1a;若出现无法显示完全的情况&#xff0c;可 V 搜索“人工智能技术与咨询”查看完整文章 人工智能、大数据、多模态大模型、计算机视觉、自然语言处理、数字孪生、深度强…

《计算机网络》(学习笔记)

目录 一、计算机网络体系结构 1.1 计算机网络概述 1.1.1 计算机网络的概念 1.1.2 计算机网络的组成 1.1.3 计算机网络的功能 1.1.4 电流交换、报文交换和分组交换 1.1.5 计算机网络的分类 1.1.6 计算机网络的性能指标 1.2 计算机网络体系结构与参考模型 1.2.1 计算机…

基于STM32的逻辑分析仪

文章目录 一、逻辑分析仪体验1、使用示例1.1 逻辑分析仪1.2 开源软件PulseView 2、核心技术2.1 技术方案2.2 信号采集与存储2.3 数据上传 3、使用逻辑分析仪4、 SourceInsight 使用技巧4.1新建工程4.2 设置工程名及工程数据目录4.3 指定源码目录4.4 添加源码4.5 同步文件4.6 操…

如何在调整节拍时间的过程中保持生产流程的稳定性?

在快节奏的工业生产领域&#xff0c;节拍时间&#xff08;Takt Time&#xff09;——即完成一个完整产品所需的标准时间&#xff0c;是维持生产效率和流程稳定性的关键指标。然而&#xff0c;市场需求的波动、技术升级或是生产线的微调&#xff0c;都可能要求我们对节拍时间进行…

云计算实训13——DNS域名解析、ntp时间服务器配置、主从DNS配置、多区域DNS搭建

一、DNS域名解析 1.正向解析 将域名解析为IP地址 DNS正向解析核心配置 (1)安装bind [rootdns ~]# yum -y install bind (2)编辑配置文件 编辑named.conf文件&#xff0c;限定访问权限 [rootdns ~]# vim /etc/named.conf 编辑named.rfc文件&#xff0c;指定要访问的域名 [ro…

VulnHub:colddbox easy

靶机下载地址 信息收集 主机发现 攻击机网段192.168.31.0/24&#xff0c;扫描同网段存活主机。 nmap 192.168.31.0/24 -Pn -T4 发现靶机&#xff0c;IP为192.168.31.176。 端口扫描 扫描靶机开放端口。 nmap 192.168.31.176 -A -p- -T4 开放了80,4512端口&#xff0c;注…

无人机之安全防护篇

在当今社会&#xff0c;园区的安全防护至关重要。无人机以其独特的视角、高效的作业能力和灵活的部署方式&#xff0c;为园区安防工作带来了前所未有的好处&#xff0c;显著提升了安全防护水平和管理效率。 一、全方位无死角的监控 与传统的固定摄像头相比&#xff0c;它不受位…

【Python Web】Flask扩展开发指南

Flask是一个轻量级的Python Web框架&#xff0c;它提供了丰富的扩展库和工具&#xff0c;可以帮助开发者快速构建Web应用。本篇博客将介绍如何进行Flask扩展开发&#xff0c;包括扩展的创建、配置、使用等方面的内容。 目录 Flask扩展开发指南 一、Flask扩展简介 二、创建Fl…

苹果CMS:资源采集站如何设置定时采集详细教程讲解

我们搭建好站点之后&#xff0c;会自定义一些采集&#xff0c;但是需要每天去手动执行&#xff0c;有时候甚至会忘记&#xff0c;那我们如何处理呢&#xff1f;今天我们就来介绍一下如何设置定时器。 如果按照官方例子来设置定时器会遇到一个问题就是采集的资源未绑定类型&…

[240728] Wikidata 介绍 | 微软与 Lumen 合作提升人工智能算力

目录 Wikidata 介绍微软与 Lumen 合作提升人工智能算力 Wikidata 介绍 中文&#xff1a; 文言: 粤语&#xff1a; 来源&#xff1a; https://www.wikidata.org/wiki/Wikidata:Introduction/zh 微软与 Lumen 合作提升人工智能算力 为了满足人工智能工作负载不断增长的需求&am…

查看路由表 netstat -r

“Kernel IP routing table” 是Linux系统中用于展示和配置IP路由的表。它告诉操作系统如何将数据包从一个网络接口发送到另一个网络或主机。下面是对您给出的路由表条目的解释&#xff1a; Destination&#xff1a;目的地地址&#xff0c;可以是具体的IP地址&#xff0c;也可…

「12月·长沙」人工智能与网络安全国际学术会议(ISAICS 2024)

人工智能与网络安全国际学术会议(ISAICS 2024)将于2024年12月20日-2024年12月22日在湖南长沙召开。会议中发表的文章将会被收录,并于见刊后提交EI核心索引。会议旨在在为国内与国际学者搭建交流平台,推进不同学科领域的融合发展&#xff0c;就当今人工智能与网络安全范畴内各学…

视觉-语言大模型应用

重磅推荐专栏: 《大模型AIGC》 《课程大纲》 《知识星球》 本专栏致力于探索和讨论当今最前沿的技术趋势和应用领域,包括但不限于ChatGPT和Stable Diffusion等。我们将深入研究大型模型的开发和应用,以及与之相关的人工智能生成内容(AIGC)技术。通过深入的技术解析和实践经…

MySQL练习05

题目 步骤 触发器 use mydb16_trigger; #使用数据库create table goods( gid char(8) primary key, name varchar(10), price decimal(8,2), num int);create table orders( oid int primary key auto_increment, gid char(10) not null, name varchar(10), price decima…

蚓链数字化生态平台:构建城市智能商业,引领协同发展新潮流

​在当今数字化飞速发展的时代&#xff0c;城市商业的运行模式正在经历着数字化变革。蚓链数字化生态平台应运而生&#xff0c;以其强大的功能和创新的理念&#xff0c;成为构建城市智能商业枢纽中心的关键力量&#xff0c;推动着平台互通、业务贯通、管理协同的全新发展格局。…