Golang基础-面向过程篇

文章目录

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

基本语法

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

package main

import (
	"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 main

import "fmt"

// 声明全局变量 方法123是可以的
var gA int = 100
var gB = 200

func main() {
	fmt.Println("gA=", gA)
}

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

var xx, yy int = 100, 200
fmt.Println("xx=", xx, "yy=", yy)

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

常量

常量用const关键字来声明

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

除此之外,还能批量声明

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

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

package main

import "fmt"

const (
	//	可以在const()中添加关键字iota,每行iota都会累加1,第一行默认是0,只能在const中使用
	BEIJING = iota * 10
	SHANGHAI
	SHENZHENG
)

func main() {
	//常量(只读)
	const length int = 10

	fmt.Println("length=", length)

	fmt.Println("beijing=", BEIJING) // 0
	fmt.Println("shanghai=", SHANGHAI) // 10
	fmt.Println("shenzheng=", SHENZHENG) // 20
}

函数

go中函数定义

func foo1(a string, b int) int {
	fmt.Println("a=", a)
	fmt.Println("b=", b)
	c := 10
	return 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 = 1000
	r2 = 2000
	return
}

import导包

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

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

lib1/2.go内容

package lib1

import "fmt"

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

func init() {
	fmt.Println("lib1.init() ...")
}

此时导包代码如下

package main

import(
	"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 main

import "fmt"

func changeValue(p *int) {
	*p = 10
}

func main() {
	var a int = 1
	changeValue(&a)
	fmt.Println(a)
}

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

defer

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

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

package main

import "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 main

import "fmt"

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

另一种定义和遍历方式

package main

import "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 main

import "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 main

import "fmt"

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

slice追加元素

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

  • 长度 (len) 是切片当前包含的元素数量,这里是 3。
  • 容量 (cap) 是切片底层数组的大小,这里是 5。
  • 切片本身存储了一个指向底层数组的指针,以及长度和容量的信息。
package main

import "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 main

import "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 main

import "fmt"

func main() {
	s := []int{1, 2, 3}

	s1 := s[0:2] // [1,2]
	s1[0] = 100
	fmt.Println(s)
	fmt.Println(s1)
}
/*输出结果
[100 2 3]
[100 2]
*/

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

package main

import "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] = 50
	fmt.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 main

import "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 main

import "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 main

import "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
*/

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

公网环境固定域名异地远程访问内网BUG管理系统

文章目录 前言1. 本地安装配置BUG管理系统2. 内网穿透2.1 安装cpolar内网穿透2.2 创建隧道映射本地服务3. 测试公网远程访问4. 配置固定二级子域名4.1 保留一个二级子域名5.1 配置二级子域名6. 使用固定二级子域名远程 前言 BUG管理软件,作为软件测试工程师的必备工具之一。在…

传输层协议 - TCP(Transmission Control Protocol)

文章目录&#xff1a; TCP 协议关于可靠性TCP 协议段格式序号与确认序号六个标志位16位窗口大小 确认应答&#xff08;ACK&#xff09;机制超时重传机制连接管理机制连接建立&#xff08;三次握手&#xff09;连接终止&#xff08;四次挥手&#xff09;TIME_WAIT 状态CLOSE_WAI…

【Vue】响应式与数据劫持

目录 前言 响应式 Vue的响应式是如何实现的 数据劫持 Vue中的data属性都具有响应式 Vue后期添加的属性如何使其具有响应式 数组的响应式处理 如何使用数组下标去修改可以具有响应式呢 前言 什么是响应式&#xff1f;数据劫持是什么&#xff1f;Vue响应式是如何实现的&a…

成都瀚网科技有限公司抖音带货靠谱么

近年来&#xff0c;随着社交媒体的兴起&#xff0c;越来越多的企业开始利用抖音等短视频平台进行产品推广和销售。成都瀚网科技有限公司也紧跟潮流&#xff0c;通过抖音平台进行带货。那么&#xff0c;成都瀚网科技有限公司的抖音带货靠谱么&#xff1f;本文将从以下几个方面进…

深入分析TaskView源码之触摸相关

问题背景 hi&#xff0c;粉丝朋友们&#xff1a; 大家好&#xff01;android 10以后TaskView作为替代ActivityView的容器&#xff0c;在课程的分屏pip自由窗口专题也进行了相关的详细介绍分析。 这里再补充一下相关的TaskView和桌面内嵌情况下的触摸分析 主要问题点&#xff…

Java零基础-Maven项目构建(最详细)

【Maven】 1.当前开发中存在的问题 1.1. 一个项目就是一个工程 如果项目非常庞大,就不适合继续使用package划分模块.最好是每一个模块对应一个项目,利于分工协作,也利于项目针对性能化的部署. 1.2. 项目中需要的jar包必须拷贝 项目中的jar包需要手动"复制" "粘…

【C++心愿便利店】No.14---C++之探索list底层原理

文章目录 前言一、list的介绍及使用1.1 list的介绍1.2 list的使用1.2.1 list的构造1.2.2 list iterator的使用1.2.3 list capacity1.2.4 list element access1.2.5 list modifiers1.2.6 list operations1.2.7 list的迭代器失效 二、list的模拟实现2.1 定义一个结构体实现list的…

配置Java环境变量不生效的解决办法

问题&#xff1a; 直接更换Java_HOME的JDK安装路径后&#xff0c;竟然环境变量不生效&#xff0c;在cmd窗口输入java -version或者javac -version后报错&#xff1f;&#xff1f;&#xff1f;这是为什么呢&#xff1f; 问题剖析&#xff1a; 在使用安装版本的JDK程序时&#…

循环链表2

循环链表的实现 对于数据结构中所有的结构而言&#xff0c;每一次都是用之前初始化&#xff08;处理一开始的随机值&#xff09;一下&#xff0c; 用完销毁&#xff08;不管有没有malloc都能用&#xff0c;用了可以保证没有动态内存泄漏了&#xff09;一下 而在C里面&#x…

激发创新,助力研究:CogVLM,强大且开源的视觉语言模型亮相

项目设计集合&#xff08;人工智能方向&#xff09;&#xff1a;助力新人快速实战掌握技能、自主完成项目设计升级&#xff0c;提升自身的硬实力&#xff08;不仅限NLP、知识图谱、计算机视觉等领域&#xff09;&#xff1a;汇总有意义的项目设计集合&#xff0c;助力新人快速实…

jdk9.0.1下载、安装、配置

下载路径xIndex of java-local/jdk/9.0.111 安装 环境变量配置 新增变量&#xff1a;JAVA_HOME 值&#xff1a;安装路径 path中新增&#xff1a;%JAVA_HOME%\bin

裸片-PCBA

裸片 PCBA&#xff0c; 薄膜&#xff0c; 邦定-COB&#xff08;chip on board&#xff09;技术是指将裸芯片直接贴在PCB 板上&#xff0c;然后用铝线或金线进行电子连接的技术

【软件工程师从0到1】- 封装 (知识汇总)

前言 介绍&#xff1a;大家好啊&#xff0c;我是hitzaki辰。 社区&#xff1a;&#xff08;完全免费、欢迎加入&#xff09;日常打卡、学习交流、资源共享的知识星球。 自媒体&#xff1a;我会在b站/抖音更新视频讲解 或 一些纯技术外的分享&#xff0c;账号同名&#xff1a;hi…

数据结构与算法实验(黑龙江大学)

实验一 顺序存储的线性表&#xff08;2 学时&#xff09; 一、实验目的 1 、掌握线性表的逻辑结构特征。 2、熟练掌握线性表的顺序存储结构的描述方法。 3 、熟练掌握顺序表上各种基本操作的实现。 二、实验内容 1 、设线性表的数据元素都为整数&#xff0c;存放在顺序表…

infercnv 三回首:深入理解infercnv为何能发nature

大家好&#xff0c;不知你是否还记得&#xff0c;前两次关于infercnv的介绍。请看这里&#xff1a; 肿瘤单细胞转录组拷贝数分析结果解读和应用 单细胞拷贝数变异 infercnv再回首 如果下载了示例数据&#xff0c;并且你已经跑了上述代码&#xff0c;不难得到这张图&#xff1…

基于Java GUI模拟银行自动取款机

一、课题描述 编写一个程序&#xff0c;模拟银行自动取款机的工作流程。主要功能如下所述: 当输入给定的卡号和密码&#xff08;初始卡号为888888和密码为123456)时&#xff0c;系统能登录ATM柜员机系统,用户可以按照以下规则进行: 查询余额:初始余额为50000元 ATM取款:每次…

【LeetCode】每日一题 2023_11_21 美化数组的最少删除数(贪心/模拟)

文章目录 刷题前唠嗑题目&#xff1a;美化数组的最少删除数题目描述代码与解题思路 结语 刷题前唠嗑 LeetCode? 启动&#xff01;&#xff01;&#xff01; 原本今天早上要上体育课&#xff0c;没那么早刷每日一题的&#xff0c;本周是体测周&#xff0c;所以体育课取消了&am…

二百零七、Flume——Flume实时采集5分钟频率的Kafka数据直接写入ODS层表的HDFS文件路径下

一、目的 在离线数仓中&#xff0c;需要用Flume去采集Kafka中的数据&#xff0c;然后写入HDFS中。 由于每种数据类型的频率、数据大小、数据规模不同&#xff0c;因此每种数据的采集需要不同的Flume配置文件。玩了几天Flume&#xff0c;感觉Flume的使用难点就是配置文件 二、…

Lightsail VPS 实例在哪些方面胜过 EC2 实例?

文章作者&#xff1a;Libai 引言 Lightsail VPS 实例和 EC2 实例是云计算领域中两种受欢迎的技术。虽然两者都提供虚拟服务器解决方案&#xff0c;但了解 Lightsail VPS 实例在哪些方面胜过 EC2 实例非常重要。在本文中&#xff0c;我们将探讨这两种技术之间的关键区别&#x…

FastReport在线设计器新版2024.1,新增多元素填充,条码元素拖放~

2024.1 版本中对报表设计器进行了更新&#xff01;我们特别关注内部架构产品的变化&#xff0c;并提高了报告的视觉易用性。我们还添加了新的对象填充和渐变。 FastReport Online Designer下载&#xff08;qun&#xff1a;585577353&#xff09;https://www.evget.com/product/…