golang的学习(代码片段)

weixin_45747080 weixin_45747080     2023-01-26     228

关键词:

非0基础的Golang的学习

Golang的优势

  • 简单的部署方式
    • 可直接编译成机器码
    • 不依赖其他库
    • 直接运行可部署
  • 静态类型的语言
    • 编译时能检查出隐藏的大多数问题
  • 语言层面的并发
    • 天生支持
    • 充分利用多核
  • 强大的标准库
    • runtime系统调度机制
    • 高效的GC垃圾回收
    • 丰富的标准库
  • 简单易学
    • 25个关键字
    • C语言简洁基因,内嵌C语法支持
    • 面向对象特征(继承、封装、多态)
    • 跨平台性
  • “大厂”领军
    • Google、fackbook
    • Tencent、Baidu(运维)、JD

main包

go run hello.go			

go build hello.go
./hello

定义变量

var a int		 	//方法一:声明变量,默认是0
var b int = 100		//方法二:声明变量,初始化一个值
var c = 100			//方法三:省去数据类型,根据值去自动匹配数据类型
d := 100			//方法四(常用):省去var关键字,自动匹配数据类型

var 
    v1 = 10
    v2 string = "abcd"
    v3 = true

Tips

方法四只能在函数体中声明使用(局部变量),全局变量不能声明和使用。

常量中使用iota

在const( )中添加一个关键字iota,每行的iota都加1,第一行的iota默认值是0。(强调每行

const a = 100

//多常量定义
const (
	b = 100
    c = 100
)
func main()  
	const (
		a = iota	//iota = 0
		b			//iota = 1
		c
		d
	)
	fmt.Println("a =",a)	//0
	fmt.Println("b =",b)	//1
	fmt.Println("c =",c)	//2
	fmt.Println("d =",d)	//3

	const (
		e = 10 * iota	// iota = 0, e= 0
		f				// iota = 1, f = 10
		g
	)
	fmt.Println("e =",e)	//0
	fmt.Println("f =",f)	//10
	fmt.Println("g =",g)	//20

	const (
		h , i = iota +1 , iota +2	//iota = 0, h = iota+1=0+1=1, i=iota+2=0+2=2
		j , k						//iota = 1, j = iota+1=1+1=2,l=iota+2=1+2=3
	)
	fmt.Println("h =",h)	//1
	fmt.Println("i =",i)	//2
	fmt.Println("j =",j)	//2
	fmt.Println("k =",k)	//3


多返回值

package main

import "fmt"

//单返回值((返回int类型)
func f1(s string, i int) int  
	fmt.Println("s =", s)
	fmt.Println("i =", i)
	//一个返回值
	return 0;


//多返回值(匿名)
func f2(s string, i int) (int, int)  
	fmt.Println("s =", s)
	fmt.Println("i =", i)
	//一个返回值
	return 0, 1;


//多返回值(具名)
func f3(s string, i int) (r1 int, r2 int)  
	//两个返回值
	r1 = 0
	r2 = 1
	return;


//多返回值(同类型,且具名)
func f4(s string, i int) (r1,r2 int)  
	fmt.Println("r1 =", r1)
	fmt.Println("r2 =", r2)
	//两个返回值
	r1 = 0
	r2 = 1
	return;



func main() 
	s := "test"
	i := 100
	r1 := f1(s, i)
	fmt.Println("r1 =",r1)
	r2, r3 := f2(s, i)
	fmt.Println("r2 =",r2, "r3 =",r3)
	f3(s,i)
	f4(s,i)


Tips

具名多返回值实质上是局部变量(有初始值)

init函数

init函数在import导包中的调用流程

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-2sEK761V-1635763248563)(C:\\Users\\wqk\\AppData\\Roaming\\Typora\\typora-user-images\\image-20211012053532973.png)]

包中可以使用init函数来进行包的一些初始化工作

import导包

import (
	"5-init/lib1"  			//使用原包名导入,调用方法为lib1.Api()
	_ "5-init/lib2"			//匿名导入包,即需要调用该包中的init(),但是不使用其中的接口
	. "5-init/lib3"			//将当前包导入并且和本包合并,直接使用Api()调用其中接口。(不推荐,可能出现命名重复	)
	mylib "5-init/lib4"		//自定义导入的包名。使用mylib.Api()调用
)

Tips

Golang中,如果import导入了包但没有使用会报错,所以导入的包必须使用,或者使用_进行匿名导入(只调用包中的init函数,不使用其中其他函数)

指针

&a			//传递a变量的地址(实参)
*p			//存储a变量的地址(形参)	
*p = 10		//通过修改a变量的地址的值的方式来修改a的值

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Xuj7CAY8-1635763248566)(C:\\Users\\wqk\\AppData\\Roaming\\Typora\\typora-user-images\\image-20211012062746855.png)]

defer语句

defer类似于C++的析构函数和Java的finalize()函数类似

多次调用defer语句的执行顺序是类似栈

package main

import "fmt"

func f1()  
	fmt.Println("f1 called...")


func f2()  
	fmt.Println("f2 called...")


func f3()  
	fmt.Println("f3 called...")



func main() 
	defer f1()
	defer f2()
	defer f3()
	
	/*
	f3 called...
	f2 called...
	f1 called...
	 */

defer在return返回值返回后执行

package main

import "fmt"

func deferFunc() int 
	fmt.Println("defer func called...")
	return 0


func returnFunc() int 
	fmt.Println("return func called...")
	return 0


func test() int 
	defer deferFunc()
	return returnFunc()


func main() 
	test()
	
	/*
	return func called...
	defer func called...
	 */

数组及其遍历

数组的定义方式

var myArray1 [10]int			//数组定义方式一:固定长度的数组(没有赋值,但有默认值0)
myArray2 := [4]int1,2,3,4		//数组定义方式二:固定长度数组并赋值
myArray3 := []int1,2,3,4		//数组定义方式三:动态数组(没有固定长度)

获取数组长度

//len()返回数组长度
length := len(myArray1)
fmt.Println("myArray1 len =",length)

数组遍历

// 数组遍历方式一:fori遍历
for i := 0; i < length; i++ 
    fmt.Println(myArray1[i])


// 数组遍历方式二:for range,可以返回index(下标)和value(元素)
for index, value := range myArray1 
    fmt.Println("index =",index, "value =",value)


// 数组遍历方式三:for range,匿名返回index或者value
for _, value := range myArray1 
    fmt.Println("value =",value)

for index, _ := range myArray1 
    fmt.Println("index =",index)

固定数组传参

//传递固定长度数组必须严格匹配数组类型以及数组长度的
func printArray(array [4]int)  
	//值拷贝
	for i := 0; i < len(array); i++ 
		fmt.Println(array[i])
	


func main() 
	myArray2 := [4]int1,2,3,4
	printArray(myArray2)		//只能传递长度为4的数组

动态数组传参

//传递动态数组不需要匹配数组长度
func printSlice(slice []int)  
	//引用拷贝
	fmt.Println("printSlice called...")
	for i := 0; i < len(slice); i++ 
		fmt.Println(slice[i])
	


func main() 
	myArray3 := []int1,2,3,4
	printSlice(myArray3)		//传递动态数组

动态数组slice

声明方式

	//声明一个切片且初始化,默认值是1,2,3
	slice1 := []int1,2,3
	fmt.Println("=====================")
	for index, value := range slice1 
		fmt.Println("index =",index,"value =",value)
	

	//声明一个切片但没有初始化且没有初始空间
	var slice2 []int
	//手动利用make来分配空间,元素有默认值
	slice2 = make([]int,5)
	fmt.Println("=====================")
	for index, value := range slice2 
		fmt.Println("index =",index,"value =",value)
	

	//声明一个切片同时给切片分配空间
	var slice3 []int = make([]int, 5)
	fmt.Println("=====================")
	for index, value := range slice3 
		fmt.Println("index =",index,"value =",value)
	

	//声明一个切片,同时分配空间,自动匹配类型
	slice4 := make([]int,5)
	fmt.Println("=====================")
	for index, value := range slice4 
		fmt.Println("index =",index,"value =",value)
	

slice追加、截取和拷贝

slice的len和cap的概念,类似于Java的ArrayList(动态数组)的size和capacity。len代表slice中是实际元素的个数,而cap代表这个slice中能够存储的元素大小,同时也支持动态扩容,在len达到cap时扩容,可以在初始化slice为其指定cap,否则默认的cap等于len

初始化slice时没有指定cap

	//初始化slice1,没有指定cap(默认cap与len相等)
	var slice1 []int = make([]int,3)
	fmt.Printf("len = %d, cap = %d, slice = %v\\n",len(slice1),cap(slice1),slice1)
	/*
	output
	len = 3, cap = 3, slice = [0 0 0]
	 */

初始化slice时指定cap

    //初始化slice2,指定cap为5
    var slice2 []int = make([]int,3,5)
    fmt.Printf("len = %d, cap = %d, slice = %v\\n",len(slice2),cap(slice2),slice2)
    /*
    output
    len = 3, cap = 5, slice = [0 0 0]
     */

向slice中添加元素(append)

	slice2 = append(slice2,5)

向元素已满的slice中添加元素(会自动扩容)

	//向已满(len=cap)的slice中添加元素,slice会自动扩容(按照一定规则)
	slice1 = append(slice1, 5)
	fmt.Printf("len = %d, cap = %d, slice = %v\\n",len(slice1),cap(slice1),slice1)
	/*
	output
	len = 4, cap = 6, slice = [0 0 0 5] (可以看到cap变大了)
	 */

从slice中截取元素(:)

	slice3 := []int0,1,2,3
	//左闭右开[0,2)即截取0到1的元素
	fmt.Printf("slice = %v\\n",slice3[0:2])		//slice = [0 1]
	//截取0到2的元素
	fmt.Printf("slice = %v\\n",slice3[:2])		//slice = [0 1]
	//截取0到末尾的元素
	fmt.Printf("slice = %v\\n",slice3[0:])		//slice = [0 1 2 3]
	//截取全部元素
	fmt.Printf("slice = %v\\n",slice3[:])		//slice = [0 1 2 3]

截取后的切片指向同一元素(浅拷贝)

	slice := slice3[:3]
	slice[0] = 100
	fmt.Printf("slice = %v\\n",slice)			//slice = [100 1 2 3]
	fmt.Printf("slice3 = %v\\n",slice3)		//slice = [100 1 2 3]

TIps

截取后的切片slice,修改其slice[0],发现slice3[0]也被修改了,说明修改前的slice3和修改后的slice底层指向同一数组

复制copy数组(深拷贝)

	slice := make([]int,len(slice3))
	//copy slice3到slice中
	copy(slice,slice3)
	fmt.Printf("slice = %v\\n",slice)			//slice = [0 1 2 3]

map

map的格式是 map[type of key]type of value,如map[string]string即key为string类型,value为string类型的map集合

声明

	//方式一:声明空map,在使用前分配空间后再赋值
	var map1 map[int]string
	map1 = make(map[int]string,10)
	//map1 = make(map[int]string)	//两种方式都可以
	map1[1] = "Java"
	map1[2] = "Golang"
	map1[3] = "JavaScript"
	fmt.Println(map1)

	//方式二:声明map的时候同时make分配空间,后再赋值
	var map2 = make(map[int]string)
	map2[1] = "Java"
	map2[2] = "Golang"
	map2[3] = "JavaScript"
	fmt.Println(map2)

	//方式三:声明map时直接赋值
	var map3 = map[int]string
		1: "Java",
		2: "Golang",
		3: "JavaScript",
	
	fmt.Println(map3)

TIps

map声明完后一定要使用make()开辟内存!一定要使用make()开辟内存!一定要使用make()开辟内存!

遍历

	myMap := map[string]string 
		"China": "Beijing",
		"USA": "DC",
		"England": "London",
	
	//遍历key和value
	for key, value := range myMap 
		fmt.Println("key =",key," value =",value)
	

删除

	//删除myMap的"USA"键值对
	delete(myMap, "USA")

修改

	//修改"England"的值为Paris
	myMap["England"] = "Paris"

引用传递

func printMap(myMap map[string]string)  
	//myMap是引用传递
	for key, value := range myMap 
		fmt.Println(key,"->",value)
	

struct结构体

与类类似,Go使用结构体来实现对象

定义结构体

//定义Student这种结构体,它包含Name、Age、Score等属性
type Student struct 
	Name string
	Age int
	Score int

结构体传参

type Student struct 
	Name string
	Age int
	Score int


func printStudent(student Student)  
	//值传递(相当于student对象的副本,无法修改其内部属性值)
	fmt.Printf("%v\\n",student)


func changeStudent(student *Student)  
	//引用传递(可以修改其内部属性值)
	student.Age = 20


func main() 
	student := Student
		Name: "wqk",
		Age: 18,
		Score: 50,
	
	printStudent(student)
	changeStudent(&student)
	printStudent(student)

封装成类

和Java类似的,利用Struct封装了Student类,并且包装好了属性的Getter和Setter,需要注意的是,由于Setter需要修改实际对象的值,所以需要传递引用对象(指针)

type Student struct 
	name string
	Age int
	Score int


func (this *Student)SetName(newName string)  
	this.Name = newName


func (this *Student) GetName() string 
	return this.Name


func (this *Student) SetAge(newAge int)  
	this.Age = newAge


func (this *Student) GetAge(

golang学习随便记3(代码片段)

...合数据类型(构造类型)数组和C语言一样,golang数组是固定长度的,索引方式也一样,不同的是,golang数组元素默认就是初始化的(为该类型的0值)。遍历方式略有不同。golang数组也可以和C一样... 查看详情

golang学习随便记9(代码片段)

goroutine和channel (1)golang有两种并发编程风格,基于CSP的goroutine+channel或者传统的共享内存多线程模型。毫无疑问,goroutine和channel是golang引以为傲的东西,虽然背后理论不是革命性的东西,但它足够有... 查看详情

golang学习---快速helloworld(代码片段)

很多著名的计算机语言都是一两个人在业余时间捣鼓出来的,但是Go语言是由Google的团队打造的。可能一些基础的知识点我不会细讲,因为这个时代你真的得快速学习,才能适应发展。来看看go的hello,packagemainimport"fmt"funcmain()fmt.... 查看详情

golang学习随便记12(代码片段)

goroutine和channel(4)并发的退出golang没有提供在一个goroutine去执行终止另一个goroutine的方法。在前面的火箭发射中,通过abortchannel实现了通知方式的goroutine终止,但这个办法不能实现一个通知两个或多个goroutine退... 查看详情

学习笔记golang之gorm学习笔记(代码片段)

一、模型定义1.模型定义模型是标准的struct,由Go的基本数据类型、实现了Scanner和Valuer接口的自定义类型及其指针或别名组成,如:typeUserstructIDuintNamestringEmail*stringAgeuint8Birthday*time.TimeMemberNumbersql.NullStringActivedAtsql 查看详情

golang学习随便记6(代码片段)

函数开始函数,这差不多开始进入golang的深水区了函数声明实际上开始使用golang写第一个程序就开始使用函数,即main函数,只是简单的main函数是没有参数列表和返回值列表的。和C语言不同,golang的返回值可以像... 查看详情

golang学习笔记6——并发(代码片段)

goroutinegolang里面没有线程的概念,取而代之的是一种叫做goroutine的东西,它是由golang的运行时去调度的,可以完成并发操作。使用goroutine很简单,直接使用go关键字就行,如下面的代码:packagemainimport( "f... 查看详情

go学习golang底层学习笔记(代码片段)

1.1.1.Go编译词法与语法分析意义:解析源代码文件,将文件中字符串序列转换成Token序列把执行词法分析的程序称为词法解析器(lexer)语法解析的结果就是抽象语法树(AST)每个AST都对应一个单独的Go语言文件,这个抽象语法树中包括当前... 查看详情

golang学习笔记5——接口(代码片段)

接口的声明golang中的接口声明方式如下:type接口名interface 方法名(参数)返回值例子://Writer接口typeWriterinterface //Write方法,参数为一个字符串 Write(sstring)//Stringer接口typeStringerinterface //String方法,参数为空, 查看详情

golang学习随便记7(代码片段)

方法golang自认为它是支持OOP的,但它的OOP和C++、Java、C#、PHP、Python等都不太一样,所以,它是用自己的方式支持了OOP思想。方法声明因为golang并没有“类”的概念,所以,golang方法是从“外部”附加到类... 查看详情

微职位golang开发工程师学习分享韩晓东(代码片段)

18年5月份接触了51CTO推出的微职位Go课程,对Golang十分喜爱。通过张长志老师的视频讲解,前后4个月的学习时间。也用Golang写了些简单的代码和例子,其中包括业余时间的,也有项目中的。今天写点Golang相关的总结,仅供各位同... 查看详情

golang源码学习:调度逻辑maingoroutine的创建(代码片段)

接上一篇继续分析一下runtime.newproc方法。函数签名newproc函数的签名为newproc(sizint32,fn*funcval)siz是传入的参数大小(不是个数);fn对应的是函数,但并不是函数指针,funcval.fn才是真正指向函数代码的指针。//go/src/runtime/runtime2.gotypefun... 查看详情

golang学习笔记2——容器和流程控制(代码片段)

golang容器golang中的容器主要有这几类:数组切片MapList下面分别记录相关用法。数组数组的定义与初始化数组的定义与初始化,用下面的代码来说明://数组定义与初始化的第一种方式vararr[2]intarr[0]=1arr[1]=20//输出... 查看详情

学习笔记golang语法学习笔记(代码片段)

一、入门go是编译型的语言,代码风格类似于C语言,其最大特点是支持并发编程,go文件后缀名为.go在命令行通过gorunhelloworld.go来运行,或先通过gobuildhelloworld.go编译,然后./helloworld执行,在windows下编译生... 查看详情

我又开始学习golang了(代码片段)

前言关于Golang,对我来说真的是一个很尴尬的事情,其实早些年就已经听说了Golang这个被大家称为“天然支持高并发”的新语言了,Golang的专栏我19就创建好了,再买了本书,买了一节网课,写了四五篇博... 查看详情

我又开始学习golang了(代码片段)

前言关于Golang,对我来说真的是一个很尴尬的事情,其实早些年就已经听说了Golang这个被大家称为“天然支持高并发”的新语言了,Golang的专栏我19就创建好了,再买了本书,买了一节网课,写了四五篇博... 查看详情

golang学习随便记10(代码片段)

goroutine和channel(2)并发的循环书中举了一个容易并行处理的问题,就是给一堆图片生成缩略图。每个缩略图都只和自己那个原始图有关,生成缩略图的工作相互独立,所以,这是一个容易并行的问题。但... 查看详情

go语言学习总结——学习golang-从零到大师(代码片段)

Pic:Gophermascotandoldlogo 让我们从Go(或Golang)的简短介绍开始。Go是由Google 工程师RobertGriesemer,RobPike和KenThompson设计的。它是一种静态类型的编译语言。第一个版本于2012年3月作为开源发布。"Go是一种开放源代码编... 查看详情