锐单电子商城 , 一站式电子元器件采购平台!
  • 电话:400-990-0325

golang入门

时间:2023-08-01 22:37:02 母连接器female

前言:

对go语言很感兴趣,所以简单学习一下是对的go语言初级入门

如果你想开始,你也可以看看个博主,他的是快速开始, 戳这里

golang语法香的一些地方:

  1. 极简单的部署方法:可直接编译成机器代码,不依赖其他库,直接运行。

  2. 静态类型语言在编译过程中可以发现大多数问题。

  3. 语言层面的并发:自然基因支持,充分利用多核

// Go 语言实现并发代码 func goFunc(i int) { 
          fmt.Println("goroutine ", i, " ...") }  func main() { 
          for i := 0; i < 1000; i  { 
           go goFunc(i) // 打开并发协程  }  time.Sleep(time.Second) }  

结果如下:

goroutine  9  ... goroutine  5  ... goroutine  0  ... goroutine  3  ... goroutine  2  ... goroutine  4  ... goroutine  8  ... goroutine  7  ... goroutine  6  ... goroutine  1  ... 
  1. 强标准库:runtime 系统调度机制,高效 CG 垃圾回收,标准仓库丰富

    “大厂” 领军:Google、facebook、Tencent、Baidu、七牛、字节 …

斐波那契数列算法不同语言 编译 运行 时间对比:

image-20220404184602983

Golang 的应用场景

1.云计算基础设施领域

代表项目:docker、kubernetes、etcd、consul、cloud flare CDN、七牛云存储 等。

2.基本后端软件

代表项目:tidb、influxdb、 cockroach 等。

3、微服务

代表项目:go-kit、 micro、 monzo bank 的 typhon、bilibili 等。

4.互联网基础设施

代表项目:以太坊、以太坊、以太坊、以太坊、以太坊、以太坊、以太坊、以太坊、以太坊、以太坊、以太坊、以太坊、以太坊、以太坊、以太坊、以太坊、以太坊、以太坊、以太坊、以太坊、以太坊、以太坊、以太坊、以太坊、以太坊、以太坊、以太坊、以太坊、以太坊、以太坊、以太坊、以太坊、以太坊、以太坊、以太坊、以太坊、以太坊、以太坊、以太坊、以太坊、以太坊、以太坊、以太坊、以太坊、以太坊、以太坊、以太坊、以太坊、以太坊、以太坊、以太坊、以太坊、以太坊、以太坊、以太坊、以太坊、以太坊、以太坊、以太坊、以太坊、以太坊、以太坊、以太坊、以太坊、以太坊、以太坊、以太坊、以太坊、以太坊、以太坊、以太坊、以太坊、hyperledger 等

Golang 的不足

1.包管理,大部分包都是托管的 Github 上。

就像我们熟悉的 maven、npm 有专门的包管理组织;

托管在 Github 上述代码很容易受到作者个人操作的影响。

2.无泛化类型。

据说很快就会有。

3、所有 Exception 都用 Error 处理(有争议)。

4、对 C 降级处理不是无缝的,没有 C 降级到 asm 那么完美。(序列化问题)

go语言占位符:

相应Unicode码点所表示的字符
占位符 说明 举例 输出
%v 默认格式的相应值。 Printf(“%v”, name) {小小}
% v 在打印结构时,将添加字段名称 Printf(“% v”, name) {Name:小小}
%#v 相应值的Go语法表示 Printf(“#v”, name) main.Human{Name:“小小”}
%T 相应值的类型Go语法表示 Printf(“%T”, name) main.Human
%% 字面上的百分号,并非值的占位符 Printf(%%) %
%t true 或 false Printf(“%t”, true) TRUE
%b 二进制表示 Printf(“%b”, 5) 101
%c Printf(“%c”, 0x4E2D)
%d 十进制表示 Printf(“%d”, 0x12) 18
%o 八进制表示 Printf(“%d”, 10) 12
%q 单引号围绕的字符字面值,由Go语法安全地转义 Printf(“%q”, 0x4E2D) ‘中’
%x 十六进制表示,字母形式为小写 a-f Printf(“%x”, 13) d
%X 十六进制表示,字母形式为大写 A-F Printf(“%x”, 13) D
%U Unicode格式:U+1234,等同于 “U+%04X” Printf(“%U”, 0x4E2D) U+4E2D
%b 无小数部分的,指数为二的幂的科学计数法, 与 strconv.FormatFloat 的 ‘b’ 转换格式一致。例如 -123456p-78
%e 科学计数法,例如 -1234.456e+78 Printf(“%e”, 10.2) 1.02E+01
%E 科学计数法,例如 -1234.456E+78 Printf(“%e”, 10.2) 1.02E+01
%f 有小数点而无指数,例如 123.456 Printf(“%f”, 10.2) 10.2
%g 根据情况选择 %e 或 %f 以产生更紧凑的(无末尾的0)输出 Printf(“%g”, 10.20) 10.2
%G 根据情况选择 %E 或 %f 以产生更紧凑的(无末尾的0)输出 Printf(“%G”, 10.20+2i) (10.2+2i)
%s 输出字符串表示(string类型或[]byte) Printf(“%s”, []byte(“Go语言”)) Go语言
%q 双引号围绕的字符串,由Go语法安全地转义 Printf(“%q”, “Go语言”) “Go语言”
%x 十六进制,小写字母,每字节两个字符 Printf(“%x”, “golang”) 676f6c616e67
%X 十六进制,大写字母,每字节两个字符 Printf(“%X”, “golang”) 676F6C616E67
%p 十六进制表示,前缀 0x Printf(“%p”, &name) 0x4f57f0
+ 总打印数值的正负号;对于%q(%+q)保证只输出ASCII编码的字符。 Printf(“%+q”, “中文”) “\u4e2d\u6587”
- 在右侧而非左侧填充空格(左对齐该区域)
# 备用格式:为八进制添加前导 0(%#o) 为十六进制添加前导 0x(%#x)或 0X(%#X),为 %p(%#p)去掉前导 0x; 如果可能的话,%q(%#q)会打印原始 (即反引号围绕的)字符串; 如果是可打印字符,%U(%#U)会写出该字符的 Unicode 编码形式(如字符 x 会被打印成 U+0078 ‘x’)。 Printf(“%#U”, ‘中’) U+4E2D
’ ’ (空格)为数值中省略的正负号留出空白(% d); 以十六进制(% x, % X)打印字符串或切片时,在字节之间用空格隔开
0 填充前导的0而非空格;对于数字,这会将填充移到正负号之后

1)变量:

变量练习:

package main
import "fmt"
func main(){ 
        
        //1.变量的声明
        var age int
        //2.变量的赋值
        age = 18
        //3.变量的使用
        fmt.Println("age = ",age);
        //声明和赋值可以合成一句:
        var age2 int = 19
        fmt.Println("age2 = ",age2);
        //不可以在赋值的时候给与不匹配的类型
        var num int = 12.56
        fmt.Println("num = ",num);
}

一次性声明多个变量:

package main
import "fmt"
//全局变量:定义在函数外的变量
var n7 = 100
var n8 = 9.7
//设计者认为上面的全局变量的写法太麻烦了,可以一次性声明:
var (
        n9 = 500
        n10 = "netty"
)
func main(){ 
        
        //定义在{}中的变量叫:局部变量
        //第一种:变量的使用方式:指定变量的类型,并且赋值,
        var num int = 18
        fmt.Println(num)
        //第二种:指定变量的类型,但是不赋值,使用默认值 
        var num2 int
        fmt.Println(num2)
        //第三种:如果没有写变量的类型,那么根据=后面的值进行判定变量的类型 (自动类型推断)
        var num3 = "tom"
        fmt.Println(num3)
        //第四种:省略var,注意 := 不能写为 = 
        sex := "男"
        fmt.Println(sex)
        fmt.Println("------------------------------------------------------------------")
        //声明多个变量:
        var n1,n2,n3 int
        fmt.Println(n1)
        fmt.Println(n2)
        fmt.Println(n3)
        var n4,name,n5 = 10,"jack",7.8
        fmt.Println(n4)
        fmt.Println(name)
        fmt.Println(n5)
        n6,height := 6.9,100.6
        fmt.Println(n6)
        fmt.Println(height)
        fmt.Println(n7)
        fmt.Println(n8)
        fmt.Println(n9)
        fmt.Println(n10)
}

进制的介绍:

十进制整数,如:99, -500, 0
八进制整数,要求以 0 开头,如:015
十六进制数,要求 0x 或 0X 开头,如:0x15
二进制:要求0b或者0B开头,如:0b11

整数类型:

整数类型介绍:简单的说,就是用于存放整数值的,比如10,-45,6712等等。

有符号整数类型:

PS:127怎么算出来的?01111111 -->二进制 —》转为十进制: 12^6 + 12^5 + 12^4 + 12^3 + 12^2 + 12^1 + 1*2^0 = 64 + 32 + 16 + 8 + 4 + 2 + 1= 127

PS:-128怎么算出来的?10000000 —>二进制 —>一看就是个负数
10000000 --》负数的二进制减1:01111111取反:10000000 —》得到一个正数 2^7 = 128加负号:-128

无符号整数类型:

表数范围的边界计算:
11111111= 2^7+127 = 128 + 127 = 25500000000 = 0

其他整数类型:

PS:Golang的整数类型,默认声明为int类型

Ps:变量占用的字节数:

package main

import (
	"fmt"
	"unsafe"
)

func main() { 
        
	var num1 int8 = 110
	fmt.Println(num1)
	var num2 uint8 = 130
	fmt.Println(num2)

	var num3 = 28
	//printf函数是格式化,%T就是填类型
	fmt.Printf("num3 的类型是: %T", num3)
	fmt.Println(unsafe.Sizeof(num3))

}

整数类型的选择:

这么多整数类型,使用的时候该如何选择呢?
Golang程序中整型变量在使用时,遵守保小不保大的原则,
即:在保证程序正确运行下,尽量使用占用空间小的数据类型

浮点类型:

【1】浮点类型介绍:
简单的说,就是用于存放小数值的,比如3.14、0.28、-7.19等等。
【2】浮点类型种类:

PS:底层存储空间和操作系统无关
PS:浮点类型底层存储:符号位+指数位+尾数位,所以尾数位只是存了 一个大概,很可能会出现精度的损失。

package main
import "fmt"
func main(){ 
        
        //定义浮点类型的数据:
        var num1 float32 = 3.14
        fmt.Println(num1)
        //可以表示正浮点数,也可以表示负的浮点数
        var num2 float32 = -3.14
        fmt.Println(num2)
        //浮点数可以用十进制表示形式,也可以用科学计数法表示形式 E 大写小写都可以的
        var num3 float32 = 314E-2 
        fmt.Println(num3)
        var num4 float32 = 314E+2
        fmt.Println(num4)
        var num5 float32 = 314e+2
        fmt.Println(num5)
        var num6 float64 = 314e+2
        fmt.Println(num6)
        //浮点数可能会有精度的损失,所以通常情况下,建议你使用:float64 
        var num7 float32 = 256.000000916
        fmt.Println(num7)
        var num8 float64 = 256.000000916
        fmt.Println(num8)
        //golang中默认的浮点类型为:float64 
        var num9 = 3.17
        fmt.Printf("num9对应的默认的类型为:%T",num9)
}

go的字符:

【1】Golang中没有专门的字符类型,如果要存储单个字符(字母),一般使用byte来保存。
【2】Golang中字符使用UTF-8编码
【3】ASCII码表:
左面是不可见字符 右面是可见字符

【4】查看UTF-8编码表:
http://www.mytju.com/classcode/tools/encode_utf8.asp

【5】代码实验:

package main
import "fmt"
func main(){ 
        
        //定义字符类型的数据:
        var c1 byte = 'a'
        fmt.Println(c1)//97
        var c2 byte = '6'
        fmt.Println(c2)//54
        var c3 byte = '('
        fmt.Println(c3 + 20)//40
        //字符类型,本质上就是一个整数,也可以直接参与运算,输出字符的时候,会将对应的码值做一个输出
        //字母,数字,标点等字符,底层是按照ASCII进行存储。
        var c4 int = '中'
        fmt.Println(c4)
        //汉字字符,底层对应的是Unicode码值
        //对应的码值为20013,byte类型溢出,能存储的范围:可以用int
        //总结:Golang的字符对应的使用的是UTF-8编码(Unicode是对应的字符集,UTF-8是Unicode的其中的一种编码方案)
        var c5 byte = 'A'
        //想显示对应的字符,必须采用格式化输出
        fmt.Printf("c5对应的具体的字符为:%c",c5)
}

【6】转义字符:
转义字符:将后面的字母表示为特殊含义

package main
import "fmt"
func main(){ 
        
        //练习转义字符:
        //\n 换行
        fmt.Println("aaa\nbbb")
        //\b 退格
        fmt.Println("aaa\bbbb")
        //\r 光标回到本行的开头,后续输入就会替换原有的字符
        fmt.Println("aaaaa\rbbb")
        //\t 制表符
        fmt.Println("aaaaaaaaaaaaa")
        fmt.Println("aaaaa\tbbbbb")
        fmt.Println("aaaaaaaa\tbbbbb")
        //\"
        fmt.Println("\"Golang\"")
}

bool类型:

【1】布尔类型也叫bool类型,bool类型数据只允许取值true和false
【2】布尔类型占1个字节。
【3】布尔类型适于逻辑运算,一般用于程序流程控制
【4】代码:

package main
import "fmt"
func main(){ 
        
        //测试布尔类型的数值:
        var flag01 bool = true
        fmt.Println(flag01)
        var flag02 bool = false
        fmt.Println(flag02)
        var flag03 bool = 5 < 9
        fmt.Println(flag03)
}

string类型:

基本介绍:

【1】介绍:
字符串就是一串固定长度的字符连接起来的字符序列。对于字符串操作的 4 个包:bytes、strings、strconv、unicode

【2】字符串的使用:

package main

import "fmt"

func main() { 
        
	//1.定义一个字符串:
	var s1 string = "你好全面拥抱Golang"
	fmt.Println(s1)
	//2.字符串是不可变的:指的是字符串一旦定义好,其中的字符的值不能改变
	var s2 string = "abc"
	//s2 = "def"
	//s2[0] = 't'
	fmt.Println(s2)
	//3.字符串的表示形式:
	//(1)如果字符串中没有特殊字符,字符串的表示形式用双引号
	//var s3 string = "asdfasdfasdf"
	//(2)如果字符串中有特殊字符,字符串的表示形式用反引号 ``
	var s4 string = ` 左右同形,左小右大 上下同形,上小下大 左右等长,错位书写 左边小时要偏上 右边小时要下落 点下有竖,点竖直对 下有横竖横高竖低 下有撇点,撇高点低 package main import "fmt" func main(){ //测试布尔类型的数值: var flag01 bool = true fmt.Println(flag01) var flag02 bool = false fmt.Println(flag02) var flag03 bool = 5 < 9 fmt.Println(flag03) }`
	fmt.Println(s4)
	//4.字符串的拼接效果:
	var s5 string = "abc" + "def"
	s5 += "hijk"
	fmt.Println(s5)
	//当一个字符串过长的时候:注意:+保留在上一行的最后
	var s6 string = "abc" + "def" + "abc" + "def" + "abc" + "def" + "abc" +
		"def" + "abc" + "def" + "abc" + "def" + "abc" + "def" + "abc" + "def" +
		"abc" + "def" + "abc" + "def" + "abc" + "def" + "abc" + "def" + "abc" +
		"def" + "abc" + "def" + "abc" + "def" + "abc" + "def" + "abc" + "def" +
		"abc" + "def" + "abc" + "def"
	fmt.Println(s6)
}

(*)字符串的常用包使用展示:

简介:

  • bytes 包操作 []byte。因为字符串是只读的,因此逐步构创建字符串会导致很多分配和复制,使用 bytes.Buffer 类型会更高。
  • strings 包提供 切割、索引、前缀、查找、替换 等功能。
  • strconv 包提供 布尔型、整型数、浮点数 和对应字符串的相互转换,还提供了双引号转义相关的转换。
  • unicode 包提供了 IsDigit、IsLetter、IsUpper、IsLower 等类似功能,用于给字符分类。

如果 string 中包含汉字,要注意:

  • UTF-8 编码中,一个汉字需要 3 个字节,通过 len() 获取的是字符串占据的字节数
str1 := "hello 世界"
fmt.Println(len(str1)) // 12
  • 如果想要得到字符串本身的长度,可以将 string 转为 rune 数组再计算:
str2 := "hello 世界"
fmt.Println(len([]rune(str2))) // 8

字符串遍历

byteuint8 的别名

runeint32 的别名,相当于 Go 里面的 char

如果包含汉字,以下遍历方式会出现乱码:

str := "你好世界!"

for i := 0; i < len(str); i++ { 
        
  fmt.Printf("%c", str[i])
}
// ä½ å¥½ä¸çï¼% 
  • 解决方案1:转成 rune 切片再遍历
str := "你好世界!"
newStr := []rune(str)
for i := 0; i < len(newStr); i++ { 
        
  fmt.Printf("%c", newStr[i])
}
// 你好世界!
  • 解决方案2:使用 range 来遍历

range 按照字符遍历,前面的 for 按照字节遍历

str := "你好世界123"
for index, value := range str { 
        
  fmt.Printf("index = %d value = %c\n", index, value)
}
index = 0 value = 你
index = 3 value = 好
index = 6 value = 世
index = 9 value = 界
index = 12 value = 1
index = 13 value = 2
index = 14 value = 3

strings包(简单操作)

字符串比较:使用 strings.Compare 比较两个字符串的字典序

strings.Compare("aaa", "bbb") // -1
strings.Compare("baa", "abb") // 1
strings.Compare("aaa", "aaa") // 0

查找函数:使用 strings.Index 查找字符串中子串的位置(第 1 个),不存在返回 -1

strings.Index("hello world", "o") // 4

类似的,使用 strings.LastIndex 查找字符串子串出现的最后一个位置,不存在返回 -1

strings.Index("hello world", "o") // 4

Count、Repeat

使用 strings.Count 统计子串在整体中出现的次数:

strings.Count("abc abc abab abc", "abc") // 3

使用 strings.Repeat 将字符串重复指定次数:

strings.Repeat("abc", 3) // abcabcabc

Replace、Split、Join

strings.Replace 实现字符串替换

str := "acaacccc"

// 局部替换 param3: 替换次数,< 0 则全部替换
strings.Replace(str, "a", "b", 2)  // bcbacccc
strings.Replace(str, "a", "b", -1) // bcbbcccc

// 全部替换
strings.ReplaceAll(str, "a", "b")  // bcbbcccc

strings.Split 实现字符串切割

str := "abc,bbc,bbd"

slice := strings.Split(str, ",")
fmt.Println(slice) // [abc bbc bbd]

strings.Join 实现字符串拼接

slice := []string{ 
        "aab", "aba", "baa"}

str := strings.Join(slice, ",")
fmt.Println(str // aab,aba,baa

go语言好美啊!

bytes 包(buffer)

Buffer 是 bytes 包中定义的 type Buffer struct {...},Bufer 是一个变长的可读可写的缓冲区。buffer缓冲区好神奇!

创建缓冲器bytes.NewBufferStringbytes.NewBuffer

func main() { 
        
	buf1 := bytes.NewBufferString("hello")
	buf2 := bytes.NewBuffer([]byte("hello"))
	buf3 := bytes.NewBuffer([]byte{ 
        'h', 'e', 'l', 'l', 'o'})

	fmt.Printf("%v,%v,%v\n", buf1, buf2, buf3)
	fmt.Printf("%v,%v,%v\n", buf1.Bytes(), buf2.Bytes(), buf3.Bytes())

	buf4 := bytes.NewBufferString("")
	buf5 := bytes.NewBuffer([]byte{ 
        })
	fmt.Println(buf4.Bytes(), buf5.Bytes())
}
hello,hello,hello
[104 101 108 108 111],[104 101 108 108 111],[104 101 108 108 111]
[] []

写入缓冲器WriteWriteStringWriteByteWriteRuneWriteTo

func main() { 
        
	buf := bytes.NewBufferString("a")
	fmt.Printf("%v, %v\n", buf.String(), buf.Bytes())
	// a, [97]

	buf.Write([]byte("b")) // Write
	buf. 

相关文章