Go语言基础讲解

2 篇文章 0 订阅
1 篇文章 0 订阅

Go语言基础

Go语言是Google开发的开源编程语言,其在多核并发上拥有原生的设计优势。

Go 语言被称为“互联网时代的C语言”。Go 语言的风格类似于C语言,其语法在C语言的基础上进行了大幅的简化。

学习路线图

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Gs3REE5F-1676735429015)(assets/luxian.png)]

https://github.com/Alikhll/golang-developer-roadmap

基本类型

整型

按长度分为:int8int16int32int64

对应的无符号整型:uint8uint16uint32uint64

浮点型

Go语言支持两种浮点型整数:float32float64

复数

complex64complex128

复数有实部和虚部,complex64的实部和虚部为32位,complex128的实部和虚部为64位。

布尔值

Go语言中以bool类型进行声明布尔型数据,布尔型数据只有truefalse两个值。

注意:

布尔类型变量的默认值为false

Go语言中不允许将整型强制转换为布尔型

布尔型无法参与数值运算,也无法与其他类型进行转换

字符串

Go语言里的字符串内部使用UTF-8编码,字符串的值为双引号中的内容。

s1 := "hello"
s2 := "祖国"

Go语言中要定义一个多行字符串时,就必须使用反引号

s1 := `这是第一行
这是第二行
这是第三行
`

反引号间换行被作为字符串中的换行,但是所有转义字符均无效,文本将会原样输出。

常用操作:

方法介绍
len求长度
+ 或 fmt.Sprintf字符串拼接
strings.Split字符串分割
strings.Contains判断是否包含
strings.HasPrefix, strings.HasSuffix前缀/后缀判断
strings.Index, strings.LastIndex子串出现的位置
strings.Join拼接

byte和rune

组成每个字符串的元素叫做“字符”,字符要用单引号包裹起来。

var c1 = '祖'
var c2 = '国'

Go语言的字符有以下两种:

uint8类型,或者叫byte型,代表了ASCII码的一个字符

rune类型,代表一个UTF-8字符

rune类型实际是一个int32

Go语言使用了特殊的rune类型来处理Unicode,让基于Unicode的文本处理更为方便,也可以使用byte类型进行默认字符串处理。

package main

import "fmt"

func main() {
	s := "百度:https://www.baidu.com/"
	// 遍历字符串
	// byte
	for i := 0; i < len(s); i++ {
		fmt.Printf("%v(%c) ", s[i], s[i])
	}
	fmt.Println()
	// rune
	for _, r := range s {
		fmt.Printf("%v(%c) ", r, r)
	}
	fmt.Println()
}

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-iCgNlWr9-1676735429017)(assets/image-20211030172712795.png)]

因为UTF8编码下一个中文汉字由3~4个字节组成,所以我们不能简单的按照字节去遍历一个包含中文的字符串,否则就会出现上面输出中第一行的结果。

字符串底层是一个byte数组,所以可以和[]byte类型相互转换。字符串是不能修改的 字符串是由byte字节组成,所以字符串的长度是byte字节的长度。 rune类型用来表示utf8字符,一个rune字符由一个或多个byte组成。

要修改字符串,需要先将其转换成[]rune或[]byte,完成后再转换为string。无论哪种转换,都会重新分配内存,并复制字节数组。

数组Array

数组是同一种数据类型的固定长度的序列。

数组长度必须是常量,而且是类型的组成部分,一旦定义,长度不能变。

如果下标在数组合法范围之外,则触发访问越界,会panic

数组是值类型,赋值和传参会复制整个数组,而不是指针。因此改变副本的值,不会改变本身的值。

值拷贝行为会造成性能问题,通常会建议使用slice,或数组指针。

package main

import (
	"fmt"
	"math/rand"
	"time"
)

// 数组求和
func sumArr(a [10]int) int {
	var sum int = 0
	for i := 0; i < len(a); i++ {
		sum += a[i]
	}
	return sum
}

func main() {
	rand.Seed(time.Now().Unix())
	var b [10]int
	for i := 0; i < len(b); i++ {
		b[i] = rand.Intn(1000)
	}
	sum := sumArr(b)
	fmt.Printf("sum=%d\n", sum)
}

切片Slice

切片是数组的一个引用,因此切片是引用类型。

切片的长度可以改变,因此,切片是一个可变的数组。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-uIwzcXtO-1676735429017)(assets/0.jpg)]

使用make动态创建slice,避免了数组必须用常量做长度的麻烦。

切片追加:用append内置函数操作切片,向slice尾部添加数据,返回新的slice对象。当数据超出slice.cap限制时,切片就会重新分配底层数组,即便原数组并未填满。

copy :函数 copy 在两个 slice 间复制数据,复制长度以 len 小的为准。两个 slice 可指向同一底层数组,允许元素区间重叠。

package main

import "fmt"

func main() {
	s := make([]int, 0, 1)
	c := cap(s)

	for i := 0; i < 50; i++ {
		s = append(s, i)
		if n := cap(s); n > c {
			fmt.Printf("cap: %d -> %d\n", c, n)
			c = n
		}
	}
}

cap: 1 -> 2
cap: 2 -> 4
cap: 4 -> 8
cap: 8 -> 16
cap: 16 -> 32
cap: 32 -> 64

指针

区别于C/C++中的指针,Go语言中的指针不能进行偏移和运算,是安全指针。

Go语言中的函数传参都是值拷贝,当我们想要修改某个变量的时候,我们可以创建一个指向该变量地址的指针变量。传递数据使用指针,而无须拷贝数据。类型指针不能进行偏移和运算。

new 与 make的区别

1、二者都是用来做内存分配的

2、make只用于slice、map以及channel的初始化,返回的还是这三个引用类型本身

3、而new用于类型的内存分配,并且内存对应的值为类型零值,返回的是指向类型的指针

package main

import "fmt"

func main() {
	var a int
	fmt.Println(&a)
	var p *int
	p = &a
	*p = 20
	fmt.Println(a)
}

Map

map是一种无序的基于key-value的数据结构,Go语言中的map是引用类型,必须初始化才能使用。

package main

import (
	"fmt"
	"math/rand"
	"sort"
	"time"
)

func main() {
	// 初始化随机种子
	rand.Seed(time.Now().UnixNano())

	var scoreMap = make(map[string]int, 200)

	for i := 0; i < 100; i++ {
		key := fmt.Sprintf("student%02d", i)
		value := rand.Intn(100)
		scoreMap[key] = value
	}

	var keys = make([]string, 0, 200)
	for key := range scoreMap {
		keys = append(keys, key)
	}
	// 对切片进行排序
	sort.Strings(keys)
	for _, key := range keys {
		fmt.Println(key, scoreMap[key])
	}
}

结构体

Go语言中没有”类“的概念,也不支持”类“的继承等面向对象的概念。

Go语言中通过结构体的内嵌再配合接口比面向对象具有更高的扩展性和灵活性。

// 类型定义
type NewInt int
// 类型别名
type MyInt = int

Go语言通过struct来实现面向对象。

// 使用type和struct关键字来定义结构体
type 类型名 struct {
    字段名 字段类型
    字段名 字段类型
    ...
}
package main

import "fmt"

type student struct {
	name string
	age  int
}

func main() {
	m := make(map[string]*student)
	stus := []student{
		{name: "p1", age: 12},
		{name: "p2", age: 30},
		{name: "p3", age: 26},
	}

	for _, stu := range stus {
		m[stu.name] = &stu
	}
	for k, v := range m {
		fmt.Println(k, "=>", v.name)
	}
}

package main

import "fmt"

// Person结构体
type Person struct {
	name string
	age  int
}

// Person的构造函数
func NewPerson(name string, age int) *Person {
	return &Person{
		name: name,
		age:  age,
	}
}

// Person的做梦方法
func (p Person) Dream() {
	fmt.Printf("%s的梦想是成为一名科学家!\n", p.name)
}

func main() {
	p1 := NewPerson("小明", 18)
	p1.Dream()
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

BLFaker84516

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值