Golang基础-面向过程篇

文章目录

    • 基本语法
    • 变量
    • 常量
    • 函数
    • import导包
      • 匿名导包
    • 指针
    • defer
    • 静态数组
    • 动态数组(slice)
      • 定义方式
      • slice追加元素
      • slice截取
    • map
      • 定义方式
      • map使用方式

基本语法

go语言输出hello world的语法如下

package mainimport ("fmt""time"
)func main() {fmt.Println("hello world")time.Sleep(1 * time.Second)
}

变量

go的变量定义语法共有四种。第一种是var [变量名] [变量类型] = [变量值],如果不写变量值,那么默认值就是0。

var a int
fmt.Println("a=", a)
fmt.Printf("type of a=%T\n", a)

第二种是声明变量时指定值

var b int = 100
fmt.Println("b=", b)
fmt.Printf("type of b=%T\n", b)

第三种是声明一个变量,省略数据类型,由go自己判断

var c = 100
fmt.Println("c=", c)

第四种是省略var,自动匹配

e := 100
fmt.Println("e=", e)
fmt.Printf("type of e=%T\n", e)

声明全局变量

package mainimport "fmt"// 声明全局变量 方法123是可以的
var gA int = 100
var gB = 200func main() {fmt.Println("gA=", gA)
}

在定义变量时,还可以定义多个

var xx, yy int = 100, 200
fmt.Println("xx=", xx, "yy=", yy)var (vv int  = 100jj bool = true
)
fmt.Println("vv=", vv, "jj=", jj)

常量

常量用const关键字来声明

const length int = 10
fmt.Println("length=", length)

除此之外,还能批量声明

const (BEIJING = 1SHANGHAI = 2SHENZHENG = 3
)

在go中有一个iota关键字,可以用来自动赋值。可以在const()中添加关键字iota,每行iota都会累加1,第一行默认是0,只能在const中使用

package mainimport "fmt"const (//	可以在const()中添加关键字iota,每行iota都会累加1,第一行默认是0,只能在const中使用BEIJING = iota * 10SHANGHAISHENZHENG
)func main() {//常量(只读)const length int = 10fmt.Println("length=", length)fmt.Println("beijing=", BEIJING) // 0fmt.Println("shanghai=", SHANGHAI) // 10fmt.Println("shenzheng=", SHENZHENG) // 20
}

函数

go中函数定义

func foo1(a string, b int) int {fmt.Println("a=", a)fmt.Println("b=", b)c := 10return c
}

如果函数有多个返回值时

func foo2(a string, b int) (int, int) {fmt.Println("a=", a)fmt.Println("b=", b)return 666, 777
}

当返回多个有形参名的,如果类型相同,可以省略一个,且形参默认值为0

func foo3(a string, b int) (r1, r2 int) {r1 = 1000r2 = 2000return
}

import导包

go中import导包的具体过程如下图所示
请添加图片描述
现在创建如下目录结构

./gostudy/5-init/
|____lib2
| |____lib2.go
|____lib1
| |____lib1.go
|____main.go

lib1/2.go内容

package lib1import "fmt"// 当前lib1提供的API
func Lib1Test() {fmt.Println("Lib1Test() ...")
}func init() {fmt.Println("lib1.init() ...")
}

此时导包代码如下

package mainimport("gostudy/5-init/lib1""gostudy/5-init/lib2"
)func main() {lib1.Lib1Test()lib2.Lib2Test()	
}

匿名导包

在导入包后如果不使用它,在编译时会直接报错,想要解决就需要通过匿名导包,即_ 包名

import (_ "gostudy/5-init/lib1"mylib2 "gostudy/5-init/lib2" // 给包起别名
)

指针

package mainimport "fmt"func changeValue(p *int) {*p = 10
}func main() {var a int = 1changeValue(&a)fmt.Println(a)
}

程序运行后,a的值被改为10

defer

在 Go 语言中,defer 关键字用于延迟执行一个函数调用,通常被用于确保一些操作在函数执行结束时得以执行,无论函数是通过正常返回还是发生了运行时恐慌(panic)。

defer 语句将函数调用推迟到包含 defer 语句的函数即将返回时执行。defer 语句经常用于资源清理、关闭文件、解锁资源等操作。
defer 语句的执行顺序是后进先出(LIFO),即最后一个 defer 语句最先执行。

package mainimport "fmt"func func1() {fmt.Println("A")
}func func2() {fmt.Println("B")
}func func3() {fmt.Println("C")
}func main() {defer func1()defer func2()defer func3()
}

以上代码的最终执行结果为CBA

静态数组

定义固定长度的数组并遍历

package mainimport "fmt"func main() {//固定长度的数组var MyArray1 [10]intfor i := 0; i < len(MyArray1); i++ {fmt.Println(MyArray1[i])}
}

另一种定义和遍历方式

package mainimport "fmt"func main() {MyArray2 := [10]int{1, 2, 3, 4}for index, value := range MyArray2 {fmt.Println("index =", index, ",value =", value)}
}

动态数组(slice)

go语言中动态数组是通过切片(slice)来实现的,切片的长度可以动态增长或缩小,这使得切片更加灵活,可以根据实际需要动态调整大小。

定义方式

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

往函数中传参并在函数中修改数组的第一个元素

package mainimport "fmt"func printArray(MyArray []int) {// _表示匿名变量for _, value := range MyArray {fmt.Println("value=", value)}MyArray[0] = 100
}func main() {MyArray := []int{1, 2, 3, 4}printArray(MyArray)fmt.Println("===========")for _, value := range MyArray {fmt.Println("value=", value)}
}
// value= 1
// value= 2
// value= 3
// value= 4
===========
// value= 100
// value= 2
// value= 3
// value= 4

slice的定义方式共有四种,方式一:声明slice1是一个切片,并且初始化,默认值是1,2,3

slice1 := []int{1, 2, 3}

方式二:声明slice是切片,但是没有分配空间。此时如果想要赋值会报错,需要通过make来分配空间

var slice1 []int
slice1 = make([]int, 3)

方式三:声明slice是切片,同时给slice分配空间,3个空间,初始化为0

var slice1 []int = make([]int, 3)

方式四:通过:=推导出是一个slice

slice1 := make([]int, 3)

想要判断一个切片是否被分配空间,可以用nil来判断

package mainimport "fmt"func main() {var slice1 []intif slice1 == nil {fmt.Println("slice未被初始化")} else {fmt.Println("slice有空间")}
}

slice追加元素

定义如下slice,创建了一个切片 numbers,使用 make 函数初始化一个长度为 3、容量为 5 的整数切片。

  • 长度 (len) 是切片当前包含的元素数量,这里是 3。
  • 容量 (cap) 是切片底层数组的大小,这里是 5。
  • 切片本身存储了一个指向底层数组的指针,以及长度和容量的信息。
package mainimport "fmt"func main() {var numbers = make([]int, 3, 5)fmt.Printf("len=%d,cap=%d,slice=%v\n", len(numbers), cap(numbers), numbers)
}
// len=3,cap=5,slice=[0 0 0]

如下图所示
请添加图片描述
此时想用如下代码向slice中增加元素,输出的结果为len=4,cap=5,slice=[0 0 0 1]

numbers = append(numbers, 1)
fmt.Printf("len=%d,cap=%d,slice=%v\n", len(numbers), cap(numbers), numbers)

当追加元素到超过数组的cap时,由于容量不足,底层数组扩展为新的容量(原容量的两倍)

package mainimport "fmt"func main() {var numbers = make([]int, 3, 5)numbers = append(numbers, 1)fmt.Printf("len=%d,cap=%d,slice=%v\n", len(numbers), cap(numbers), numbers)numbers = append(numbers, 2)fmt.Printf("len=%d,cap=%d,slice=%v\n", len(numbers), cap(numbers), numbers)numbers = append(numbers, 6)fmt.Printf("len=%d,cap=%d,slice=%v\n", len(numbers), cap(numbers), numbers)
}
/* 输出结果
len=4,cap=5,slice=[0 0 0 1]
len=5,cap=5,slice=[0 0 0 1 2]
len=6,cap=10,slice=[0 0 0 1 2 6]
*/

以上代码的执行过程如下:

  1. 初始时,切片 numbers 的长度是 3,容量是 5,内容是 [0 0 0]。
  2. 向切片追加元素 1,长度变为 4,容量仍然是 5,内容变为 [0 0 0 1]。由于容量未超过预分配的容量,底层数组未发生扩展。
  3. 向切片追加元素 2,长度变为 5,容量仍然是 5,内容变为 [0 0 0 1 2]。
  4. 向切片追加元素 6,由于容量不足,底层数组扩展为新的容量(原容量的两倍,即 5*2=10)。切片的长度变为 6,容量变为 10,内容变为 [0 0 0 1 2 6]。

slice截取

和Python类似

s := []int{1, 2, 3}
s1 := s[0:2] // [1,2]

代码创建了一个切片 s 包含元素 [1, 2, 3],然后通过 s[0:2] 的切片操作创建了一个新的切片 s1,该切片包含 s 的索引 0 到 1 的元素。这样的切片操作是左闭右开的,所以 s1 将包含索引 0 和 1 对应的元素,即 [1, 2]。

需要注意的是这个切片操作是基于原始切片 s 的,所以对 s1 的修改也会反映在 s 中,因为s和s1的指针指向的是同一个地址,新切片和原始切片共享相同的底层数组。例如,如果你修改了 s1 中的元素,s 中对应的元素也会被修改。通过以下代码执行的结果可以看出。

package mainimport "fmt"func main() {s := []int{1, 2, 3}s1 := s[0:2] // [1,2]s1[0] = 100fmt.Println(s)fmt.Println(s1)
}
/*输出结果
[100 2 3]
[100 2]
*/

如果想把数组内容拷贝到另一个地址的数组中,可以用copy来进行深拷贝。如果 s2 的长度小于 s 的长度,copy 将只复制 s2 的长度个元素。

package mainimport "fmt"func main() {s := []int{1, 2, 3}s1 := s[0:2] // [1,2]s[0] = 100//copy深拷贝s2 := make([]int, 3)copy(s2, s)s[0] = 50fmt.Println(s)fmt.Println(s1)fmt.Println(s2)
}

以上代码开辟了新的数组空间s2,并把s数组copy到s2中,即使把s中第一个元素的值改为50,s2也不受影响,而s1会跟随s也改为50。

map

在Go语言中,map 是一种用于存储键值对的数据结构,也被称为字典或关联数组。

定义方式

map的定义方式共有三种。

第一种:声明MyMap1是一种map类型,key和value都是string。在声明后使用make函数为MyMap1分配了空间,并指定了容量为10。

var MyMap1 map[string]string
if MyMap1 == nil {fmt.Println("MyMap1是一个空map")
}
// 分配空间
MyMap1 = make(map[string]string, 10)MyMap1["one"] = "java"
MyMap1["two"] = "c++"
MyMap1["three"] = "go"fmt.Println(MyMap1)
/*输出结果
map[one:java three:go two:c++]
*/

在最终输出时,由于map是无序的,键值对的顺序可能会不同。

第二种:直接使用make为map创建空间

MyMap2 := make(map[int]string)
MyMap2[1] = "java"
MyMap2[2] = "c++"
MyMap2[3] = "go"
fmt.Println(MyMap2)
/*输出结果
map[1:java 2:c++ 3:go]
*/

第三种:在声明map时直接定义其中的键值对

MyMap3 := map[string]string{"one":   "php","two":   "c","three": "python",
}
fmt.Println(MyMap3)
/*输出结果
map[one:php three:python two:c]
*/

map使用方式

map的增删改查实现如下:

package mainimport "fmt"func main() {cityMap := make(map[string]string)//添加cityMap["China"] = "beijing"cityMap["Japan"] = "Tokyo"cityMap["USA"] = "NewYork"//遍历for key, value := range cityMap {fmt.Println("key =", key)fmt.Println("value =", value)}//删除delete(cityMap, "China")//修改cityMap["USA"] = "DC"fmt.Println("===========")for key, value := range cityMap {fmt.Println("key =", key)fmt.Println("value =", value)}
}
/*输出结果
key = China
value = beijing
key = Japan
value = Tokyo
key = USA
value = NewYork
===========
key = Japan
value = Tokyo
key = USA
value = DC
*/

函数传参,通过定义了一个名为 printMap 的函数,该函数接受一个 map[string]string 类型的参数 cityMap,并在循环中遍历该 map 输出每个键值对的键和值。以下代码的输出结果同上。

package mainimport "fmt"func printMap(cityMap map[string]string) {for key, value := range cityMap {fmt.Println("key =", key)fmt.Println("value =", value)}
}func main() {cityMap := make(map[string]string)//添加cityMap["China"] = "beijing"cityMap["Japan"] = "Tokyo"cityMap["USA"] = "NewYork"printMap(cityMap)//删除delete(cityMap, "China")//修改cityMap["USA"] = "DC"fmt.Println("===========")printMap(cityMap)
}

需要注意的是,向函数中传递的cityMap是一个引用传递,因此两个map指向的是同一个地址空间,在函数内对 map 的修改会影响到原始的 map。

package mainimport "fmt"func printMap(cityMap map[string]string) {for key, value := range cityMap {fmt.Println("key =", key)fmt.Println("value =", value)}
}func changeValue(cityMap map[string]string) {cityMap["UK"] = "London"
}func main() {cityMap := make(map[string]string)//添加cityMap["China"] = "beijing"cityMap["Japan"] = "Tokyo"cityMap["USA"] = "NewYork"printMap(cityMap)//删除delete(cityMap, "China")//修改cityMap["USA"] = "DC"changeValue(cityMap)fmt.Println("===========")for key, value := range cityMap {fmt.Println("key =", key)fmt.Println("value =", value)}
}
/*输出结果
key = USA
value = NewYork
key = China
value = beijing
key = Japan
value = Tokyo
===========
key = UK
value = London
key = Japan
value = Tokyo
key = USA
value = DC
*/

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

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

相关文章

Django 入门学习总结2 创建一个投票系统

通过学习&#xff0c;我们可以实现一个简单的投票系统。这个投票系统有两部分组成。 公共部分&#xff0c;公众可以查看和进行投票。管理员可以进行增加、删除、修改投票信息。 这里投票系统Python语言版本为3.10.13&#xff0c;Django Web框架版本为4.2.7。 投票系统的实现…

维基百科文章爬虫和聚类【二】:KMeans

维基百科是丰富的信息和知识来源。它可以方便地构建为带有类别和其他文章链接的文章&#xff0c;还形成了相关文档的网络。我的 NLP 项目下载、处理和应用维基百科文章上的机器学习算法。 一、说明 在我的上一篇文章中&#xff0c;展示了该项目的轮廓&#xff0c;并奠定了其基础…

LOJ #10134. 「一本通 4.4 练习 1」Dis

分析 根据数据范围分析一下复杂度&#xff0c;Floyd和dj算法都必爆。 发现题目说的是树&#xff0c;还是边还是双向的&#xff08;树本身就是无向的&#xff0c;连通无回路的无向图叫做无向树&#xff0c;简称树。如果题目说了树&#xff0c;那么默认边就是双向的&#xff09…

(二)汇编语句组成

一个完整的 RISC-V 汇编程序有多条 语句&#xff08;statement&#xff09; 组成。 一条典型的 RISC-V 汇编 语句 由 3 部分组成&#xff1a; 1.标签 List item label&#xff08;标签&#xff09;: 标签是标识程序位置的记号。通常定义一个名称然后加上":"后缀。…

PP-PicoDet算法训练行人检测模型

PP-PicoDet算法训练行人检测模型 1&#xff0c;效果图2&#xff0c;PP-PicoDet介绍3&#xff0c;使用飞浆框架训练模型1&#xff0c;准备好图片和对应的标注文件2&#xff0c;划分训练集和验证集3&#xff0c;vi label_list.txt4&#xff0c;目录结构5&#xff0c;修改配置文件…

【Windows 常用工具系列 11 -- 福昕PDF搜索高亮过的文本】

文章目录 福昕 PDF 搜索高亮过的文本 福昕 PDF 搜索高亮过的文本 在 pdf 文档阅读过程中&#xff0c;我们需要经常高亮一些文本&#xff0c;以方便下次阅读时找到重点。我这边使用的是 福昕PDF 阅读器&#xff0c;下面就介绍下如何在福昕阅读器中搜索已经高亮过的文本。

场景交互与场景漫游-交运算与对象选取(8-1)

交运算与对象选取 在面对大规模的场景管理时&#xff0c;场景图形的交运算和图形对象的拾取变成了一项基本工作。OSG作为一个场景管理系统&#xff0c;自然也实现了场景图形的交运算&#xff0c;交运算主要封装在osgUtil 工具中在OSG中&#xff0c;osgUtil是一个非常强有力的工…

python实战—核心基础4(超市购物小票随机抽奖程序) lv1

目录 一、核心代码解释 二、代码 三、运行截图 一、核心代码解释 1、random() 函数 描述 random() 方法返回随机生成的一个实数&#xff0c;它在[0,1)范围内。 语法 以下是 random() 方法的语法: import randomrandom.random() 注意&#xff1a;random()是不能直接访问…

OpenLDAP配置web管理界面PhpLDAPAdmin服务-centos9stream

之前已经发了一篇关于centos9下面配置openldap多主高可用集群的内容&#xff0c;不会配置ldap集群的请参考&#xff1a;服务器集群配置LDAP统一认证高可用集群&#xff08;配置tsl安全链接&#xff09;-centos9stream-openldap2.6.2-CSDN博客 这里跟着前篇文章详细说明如何配置…

在回调之间共享数据

可以在 App 中为 UI 组件编写回调函数&#xff0c;以指定用户与其交互时的行为方式。 在具有多个相互依赖的 UI 组件的 App 中&#xff0c;回调函数通常必须访问主 App 函数中定义的数据&#xff0c;或与其他回调函数共享数据。例如&#xff0c;如果创建一个具有列表框的 App&a…

.Net中Redis的基本使用

前言 Redis可以用来存储、缓存和消息传递。它具有高性能、持久化、高可用性、扩展性和灵活性等特点&#xff0c;尤其适用于处理高并发业务和大量数据量的系统&#xff0c;它支持多种数据结构&#xff0c;如字符串、哈希表、列表、集合、有序集合等。 Redis的使用 安装包Ser…

云计算赛项容器云2023搭建

部署容器云平台[5 分] 使 用 OpenStack 私 有 云 平 台 创 建 两 台 云 主 机 &#xff0c; 云 主 机 类 型 使 用 4vCPU/12G/100G 类型&#xff0c;分别作为 Kubernetes 集群的 Master 节点和 node 节点&#xff0c; 然后完成 Kubernetes 集群的部署&#xff0c;并完成 Istio …

【MySql】13- 实践篇(十一)

文章目录 1. 自增主键为什么不是连续的&#xff1f;1.1 自增值保存在哪儿&#xff1f;1.2 自增值修改机制1.2.1 自增值的修改时机1.2.2 自增值为什么不能回退? 1.3 自增锁的优化1.3.1 自增锁设计历史 2. Insert语句为何很多锁?2.1 insert … select 语句2.2 insert 循环写入2…

鸿蒙4.0真机调试踩坑

传言鸿蒙next版本将不再兼容Android&#xff0c;所以领导安排做下鸿蒙开发的调研工作。 鸿蒙开发指南其实已经非常的友好了。但是鸿蒙开发本身还是有些坑要踩&#xff0c;这篇文章主要讲了鸿蒙真机调试问题。 目前手上的真机为华为 nova6&#xff0c;处理器为麒麟990.鸿蒙系统…

AI绘画使用Stable Diffusion(SDXL)绘制三星堆风格的图片

一、前言 三星堆文化是一种古老的中国文化&#xff0c;它以其精湛的青铜铸造技术闻名&#xff0c;出土文物中最著名的包括青铜面具、青铜人像、金杖、玉器等。这些文物具有独特的艺术风格&#xff0c;显示了高度的工艺水平和复杂的社会结构。 青铜面具的巨大眼睛和突出的颧骨&a…

11.16~11.19绘制图表,导入EXCEL中数据,进行拟合

这个错误通常是由于传递给curve_fit函数的数据类型不正确引起的。根据你提供的代码和错误信息&#xff0c;有几个可能的原因&#xff1a; 数据类型错误&#xff1a;请确保ce_data、lg_data和product_data是NumPy数组或类似的可迭代对象&#xff0c;且其元素的数据类型为浮点数。…

C#,怎么修改(VS)Visual Studio 2022支持的C#版本

一些文字来自于 Microsoft . &#xff08;只需要读下面的红色文字即可&#xff01;&#xff09; 1 C# 语言版本控制 最新的 C# 编译器根据项目的一个或多个目标框架确定默认语言版本。 Visual Studio 不提供用于更改值的 UI&#xff0c;但可以通过编辑 .csproj 文件来更改值。…

基于SSM的学院网站设计与实现

末尾获取源码 开发语言&#xff1a;Java Java开发工具&#xff1a;JDK1.8 后端框架&#xff1a;SSM 前端&#xff1a;Vue 数据库&#xff1a;MySQL5.7和Navicat管理工具结合 服务器&#xff1a;Tomcat8.5 开发软件&#xff1a;IDEA / Eclipse 是否Maven项目&#xff1a;是 目录…

4.3 Windows驱动开发:监控进程与线程对象操作

在内核中&#xff0c;可以使用ObRegisterCallbacks这个内核回调函数来实现监控进程和线程对象操作。通过注册一个OB_CALLBACK_REGISTRATION回调结构体&#xff0c;可以指定所需的回调函数和回调的监控类型。这个回调结构体包含了回调函数和监控的对象类型&#xff0c;还有一个A…

Camtasia2024年破解版安装包如何下载?

作为一个互联网人&#xff0c;没少在录屏软件这个坑里摸爬滚打。培训、学习、游戏、影视解说……都得用它。这时候没个拿得出手的私藏软件&#xff0c;还怎么混&#xff1f;说实话&#xff0c;录屏软件这两年也用了不少&#xff0c;基本功能是有但总觉得缺点什么&#xff0c;直…