【Go语言从入门到实战】基础篇

Go语言从入门到实战 — 基础篇

First Go Program

编译 & 运行

image-20230426195714507

基本程序结构

image-20230426200702701

应用程序入口

image-20230426200721500

package main

import "fmt"

func main() {
    fmt.Println("Hello World")
}

退出返回值

image-20230426200739987

package main

import (
	"fmt"
	"os"
)

func main() {
	fmt.Println("Hello World")
    os.Exit(-1)
}

image-20230426201336110

获取命令行参数

image-20230426200753974

package main

import (
    "fmt"
    "os"
)

func main() {
	fmt.Println(os.Args[0])
	fmt.Println(os.Args[1])
	fmt.Println("Hello World")
	os.Exit(-1)
}

argslyc

Test

编写测试程序

image-20230426201803096

package test

import "testing"

func TestFirstTry(t *testing.T) {
	t.Log("My first try!")
}

image-20230426202100002

变量 & 常量

变量如果定义后未使用,则编译不通过,这是Go语言的特性,极大的减少无效内存。

实现Fibonacci数列

package fib

import (
    "fmt"
    "testing"
)

func TestFibList(t *testing.T) {
   	var a int = 1
    var b int = 1
    //var (
    //	a int = 1
    //	b     = 1
    //)
    //a := 1
    //b := 1
    fmt.Print(a)
    for i := 0; i < 5; i++ {
      	fmt.Print(" ", b)
      	tmp := a
      	a = b
        b = tmp + a
    }
    fmt.Println()
}

image-20230426202240328

变量赋值

image-20230426202149323

// 变量交换
func TestExchange(t *testing.T) {
    a := 1
    b := 2
    // 不需要tmp中间值
    //tmp := a
    //a = b
    //b = tmp
    a, b = b, a
    t.Log(a, b)
}

image-20230426202647390

常量定义

image-20230426202722084

package constant_test

import "testing"

const (
    Monday = 1 + iota
    Tuesday
    Wednesday
)

func TestConstantTry(t *testing.T) {
    t.Log(Monday, Tuesday, Wednesday)
}

image-20230426202813313

package constant_test

import "testing"

const (
	Readable   = 1 << iota // 可读 最后一位为1
	Writable               // 可写 倒数第二位为1
	Executable             // 可执行 倒数第三位位3
)

func TestConstantTry1(t *testing.T) {
	a := 7 // 0111
	t.Log(a&Readable == Readable, a&Writable == Writable, a&Executable == Executable)
}

image-20230426202932394

数据类型

基本数据类型

image-20230426203020954

  • byteuint8 别名,无符号8位整型
  • rune:代表 Unicode 编码值,跟字符串 string 相关,后面讲
  • comlpex:复数有实部和虚部,complex64的实部和虚部为32位,complex128的实部和虚部为64位
    • TODO 不知道怎么用

类型转换

image-20230426203607582

package type_test

import (
    "math"
    "testing"
)

type MyInt int64

func TestImplicit(t *testing.T) {
    var a int = 1
    var b int64
  	// 显示类型转换(不支持隐式转换)
    b = int64(a)
  	//b=a // Cannot use 'a' (type int) as the type int64
    var c MyInt
    c = MyInt(b) // 别名类型也不可以隐式转换
    t.Log(a, b, c)

    t.Log(math.MaxInt) // 类型的预定义值
}

指针

不支持🙅🏻‍♀️指针运算。

// 指针
func TestPoint(t *testing.T) {
    a := 1
    aPtr := &a
    //aPtr += 1 // go语言不支持指针运算
    t.Log(a, aPtr)
    t.Logf("%T %T", a, aPtr)
}

image-20230427095947395

字符串

string是值类型,其默认的初始化值为空字符串,而不是 nil

// 字符串
func TestString(t *testing.T) {
    var s string
    t.Log("*" + s + "*") // string默认是空字符串
    t.Log(len(s))
}

image-20230427100059787

修改字符串

func TestChangeString(t *testing.T) {
	s1 := "big"
	// 强制类型转换
	byteS1 := []byte(s1)
	byteS1[0] = 'p'
	t.Log(string(byteS1))

	s2 := "白萝卜"
	runeS2 := []rune(s2)
	runeS2[0] = '红'
	t.Log(string(runeS2))
}

运算符

算术运算符

A := 10
B := 20

image-20230427100228162

比较运算符

A := 10
B := 20

image-20230427101007973

== 比较数组

image-20230427101419905

// 数组的比较
func TestCompareArray(t *testing.T) {
	a := [...]int{1, 2, 3, 4}
	b := [...]int{1, 3, 4, 5}
	//c := [...]int{1, 4, 5, 6, 7}
	d := [...]int{1, 2, 3, 4}
	t.Log(a == b)
	//t.Log(a == c) // 无法比较长度不同的数组
	t.Log(a == d)
}

image-20230427101434930

逻辑运算符

image-20230427101542130

位运算符

A := 60 // 0011 1100
B := 13 // 0000 1101

image-20230427111130058

按位清零

Go的特性:&^

image-20230427111250087

package operator_test

import "testing"

const (
	Readable   = 1 << iota // 可读 最后一位为1
	Writable               // 可写 倒数第二位为1
	Executable             // 可执行 倒数第三位位3
)

// 按位清零
func TestBitClear(t *testing.T) {
	a := 7
	a &^= Readable // 清零
	t.Log(a&Readable == Readable, a&Writable == Writable, a&Executable == Executable)
}

image-20230427111420383

循环

image-20230427131239226

代码示例

image-20230427131310592

条件

if

image-20230427131606448

image-20230427131740986

func TestIfMultiSec(t *testing.T) {
	if a := 1 == 1; a {
		t.Log("1 == 1")
	}
	// 比较常用的if使用
	/*if v, err := someFun(); err == nil {
		t.Log(v)
	} else {
		t.Log("error!")
	}*/
}

switch

image-20230427132038273

switch 中的 case 自带 break。

// go的switch支持多个变量
func TestSwitchMultiCase(t *testing.T) {
	for i := 0; i < 5; i++ {
		switch i {
		case 0, 2:
			t.Log("偶数")
		case 1, 3:
			t.Log("奇数")
		default:
			t.Log("not 0-3")
		}
	}
}

// go的switch还支持条件表达式
func TestSwitchCaseCondition(t *testing.T) {
	for i := 0; i < 5; i++ {
		switch {
		case i%2 == 0:
			t.Log("偶数")
		case i%1 == 0:
			t.Log("奇数")
		default:
			t.Log("not 0-3")
		}
	}
}

数组

数组的声明

image-20230426201812637

func TestArrayInit(t *testing.T) {
	var arr [3]int
	arr1 := [4]int{1, 2, 3, 4}
	arr2 := [...]int{1, 3, 5, 7} // 如果不知道需要创建多大的空间 可用'...'
	t.Log(arr[1], arr1[1], arr2[1])

	arr3 := [...][3]int{{3, 4}, {1, 2, 3}} // 二维数组只有第一维可以用'...' 二维必须是确定的值
	t.Log(arr3[0][0])
}

数组元素遍历

image-20230426201848179

func TestArrayTravel(t *testing.T) {
	arr := [...]int{1, 3, 4, 5}
	for i := 0; i < len(arr); i++ {
		t.Log(arr[i])
	}

    // 类似java增强for循环
	for idx, e := range arr {
		t.Log(idx, e)
	}
    
    // 如果不想要idx这个值,则可以使用下划线'_'(空标识符)
    // 空标识符可用于任何语法需要变量名但程序逻辑不需要的时候,
    // 例如, 在循环里,丢弃不需要的循环索引, 保留元素值。
    for _, e := range arr {
		t.Log(e)
	}
}

数组截取

image-20230426201859153

func TestArraySection(t *testing.T) {
	arr := [...]int{1, 2, 3, 4, 5}
	arrSec := arr[:3]
	t.Log(arrSec)
	arrSec2 := arr[3:]
	t.Log(arrSec2)
    arrSec3 := arr[0:3] // [0, 3)
	t.Log(arrSec3)
}

image-20230427132834106

切片

切片(Slice)是一个拥有相同类型元素的可变长度的序列。它是基于数组类型做的一层封装。它非常灵活,支持自动扩容。

切片是一个引用类型(结构体),它的内部结构包含地址长度容量。切片一般用于快速地操作一块数据集合。

切片内部结构

image-20230426201919359

切片声明

image-20230427140537065

func TestSliceInit(t *testing.T) {
	var s0 []int // 声明方式很像数组,但它不需要声明大小,因为它是可变长的
	t.Log(len(s0), cap(s0))
	s0 = append(s0, 1)
	t.Log(len(s0), cap(s0))

	s1 := []int{1, 2, 3, 4}
	t.Log(len(s1), cap(s1))

	s2 := make([]int, 3, 5) // 使用make()函数,声明切片的长度为3,容量为5
	t.Log(len(s2), cap(s2))

	t.Log(s2[0], s2[1], s2[2]) // 只初始化了前3个元素
	//t.Log(s2[3], s2[4]) // runtime error: index out of range [3] with length 3
}

image-20230427140246470

切片如何实现可变长

func TestSliceGrowing(t *testing.T) {
	var s []int
	for i := 0; i < 10; i++ {
		s = append(s, i)
		t.Log(len(s), cap(s))
	}
}

空间不够自动扩容,每次扩容为原来的2倍。

所以为什么append()函数要写成这样:s = append(s, i),重新赋值给s,因为结构体指向的连续存储空间每次扩容都会发生变化,创建一个新的连续存储空间,把原来的值拷贝过来,所以需要重新赋值。

所以我们不需要关注切片创建的大小,使用起来很方便,但也不能无限制的利用切片的这种特性,如果数据过多那么拷贝的代价是非常大的。

image-20230429200943870

切片共享存储结构

image-20230429202216796

func TestSliceShareMemory(t *testing.T) {
	year := []string{"Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"}
	Q2 := year[3:6]
	t.Log(Q2, len(Q2), cap(Q2))

	summer := year[5:8]
	t.Log(summer, len(summer), cap(summer))

	summer[0] = "UnKnow"
	t.Log(Q2)
}

image-20230427143054133

数组 vs 切片

image-20230427143400881

  • 数组不可以伸缩,但可以比较。
  • 切片可以伸缩,但不可以比较。

Map集合

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

Map声明

image-20230427143735245

func TestMapInit(t *testing.T) {
	m1 := map[int]int{1: 1, 2: 4, 3: 9}
	t.Log(m1[2])
	t.Logf("len m1 = %d", len(m1))
	m2 := map[int]int{}
	m2[4] = 16
	t.Logf("len m2 = %d", len(m2))
	m3 := make(map[int]int, 10)
	t.Logf("len m3 = %d", len(m3))
}

image-20230427144235345

Map中value的默认值

/*
  我们获取map的key有两种情况
  1.key不存在
  2.key存在,但value为空
*/
func TestAccessNotExistingKey(t *testing.T) {
	m := map[int]int{}
	t.Log(m[1]) // 不存在的value值,为0
	m[2] = 0    // 我们将key为2的value设置为0
	t.Log(m[2]) // value为0
	// 也就是说go中的map,无论value是否存在,他们都会被默认赋值为0
	// 这就跟java不一样了,java会返回null,则会造成空指针异常,而go就不会出现这个问题
	// 但我们无法判断他是默认值还是我们赋的值,所以go需要我们自己判断这个值是否存在
	if v, ok := m[3]; ok {
		t.Logf("key 3's value is %d", v)
	} else {
		t.Log("key 3 is not existing.")
	}
}

image-20230427145058403

Map的遍历

func TestTravelMap(t *testing.T) {
	m1 := map[int]int{1: 1, 2: 4, 3: 9}
	for k, v := range m1 {
		t.Log(k, v)
	}
}

image-20230427150243724

Map与工厂模式

image-20230427150357082

func TestMapWithFunValue(t *testing.T) {
	m := map[int]func(op int) int{}
	m[1] = func(op int) int { return op }
	m[2] = func(op int) int { return op * op }
	m[3] = func(op int) int { return op * op * op }
	t.Log(m[1](2), m[2](2), m[3](2))
}

image-20230524200651879

实现Set

image-20230427161213316

// 使用map构建set
func TestMapForSet(t *testing.T) {
	mySet := map[int]bool{} // key的类型自己设定,value的类型只能是bool类型
	mySet[1] = true
	// 所以我们判断元素是否存在则直接判断value是否为true
	for i := 1; i < 3; i++ {
		if mySet[i] {
			t.Logf("%d is existing", i)
		} else {
			t.Logf("%d is not existing", i)
		}
	}
	delete(mySet, 1) // 删除元素
	t.Log(mySet[1] == true)
    t.Log(len(mySet)) // 元素个数
}

image-20230427164327962

字符串

string

image-20230427164433493

func TestString(t *testing.T) {
	var s string
	t.Log(s) // 初始化默认零值""
	s = "hello"
	t.Log(len(s))
	//s[1] = '3' // string是不可变的byte slice [cannot assign to s[1]]
	s = "\xE4\xB8\xA5" // 可以存储任何二进制数据
	t.Log(s)
	t.Log(len(s))
	s = "中"
	t.Log(len(s)) // 是byte数
}

image-20230427170214683

Unicode & UTF8

image-20230427185713325

func TestString(t *testing.T) {
	var s string
	s = "中"
	t.Log(len(s)) // 是byte数

	c := []rune(s) // rune 可以取出字符串里的unicode
	t.Log(len(c))
	// t.Log("rune size:", unsafe.Sizeof(c[0]))
	t.Logf("中 unicode %x", c[0])
	t.Logf("中 UTF8 %x", s)
}

image-20230427190155522

编码与存储

image-20230427191808339

格式化输出

func TestStringToRune(t *testing.T) {
	s := "中华人民共和国"
	for _, c := range s {
		t.Logf("%[1]c %[1]d", c) // [1]就是只和第1个参数匹配,以%c和%d格式化
	}
}

image-20230427194822355

常用函数

func TestStringFun(t *testing.T) {
	s := "A,B,C"
	parts := strings.Split(s, ",") // 分割
	for _, part := range parts {
		t.Log(part)
	}
	t.Log(strings.Join(parts, "-")) // 拼接

	s = strconv.Itoa(10)     // 整数转字符串
	t.Log(reflect.TypeOf(s)) // 利用反射查看元素类型
	a, _ := strconv.Atoi(s)  // 字符串转整形 会额外返回一个错误值
	t.Log(reflect.TypeOf(a))
}

函数

函数式编程

image-20230428104545386

// 多个返回值的函数
func returnMultiValues() (int, int) {
	return rand.Intn(10), rand.Intn(20)
}

// 计算函数操作的时长
func timeSpend(inner func(op int) int) func(op int) int {
	// 类似装饰者模式,对原来的函数进行了一层包装
	return func(n int) int {
		start := time.Now()
		ret := inner(n)
		fmt.Println("time spend:", time.Since(start).Seconds())
		return ret
	}
}

// 休眠1s的函数
func slowFun(op int) int {
	time.Sleep(time.Second * 1)
	return op
}

func TestFunc(t *testing.T) {
	a, _ := returnMultiValues()
	t.Log(a)

	tsSF := timeSpend(slowFun) // 调用计算时长方法 传入一个函数
	t.Log(tsSF(10)) // 输出我们传入的值
}

可变参数

image-20230428105748557

func Sum(ops ...int) int {
	ret := 0
	for _, op := range ops {
		ret += op
	}
	return ret
}

func TestVarParam(t *testing.T) {
	t.Log(Sum(1, 2, 3))
	t.Log(Sum(1, 2, 3, 4, 5))
}

image-20230524200907347

延迟执行函数defer

类似于 java 的 try/finally

image-20230428110134493

func Clear() {
	fmt.Println("Clear resources.")
}

func TestDefer(t *testing.T) {
    defer Clear() // 使用defer关键字调用Clear()函数 即使出现异常也可以保证释放资源
	fmt.Println("Start")
	panic("err") // Exception 抛异常
}

image-20230524201000231

笔记整理自极客时间视频教程:Go语言从入门到实战

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

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

相关文章

Unity3D :使用 UXML 实例作为模板

推荐&#xff1a;将 NSDT场景编辑器 加入你的3D工具链 3D工具集&#xff1a; NSDT简石数字孪生 使用 UXML 实例作为模板 您可以将现有 UXML 文档实例化为 UXML 文档中的模板作为模板实例&#xff0c;类似于预制件 在 Unity 中工作。 使用 UXML 文档作为模板 要将项目中的现有…

MySQL高级篇——覆盖索引、前缀索引、索引下推、SQL优化、主键设计

导航&#xff1a; 【Java笔记踩坑汇总】Java基础进阶JavaWebSSMSpringBoot瑞吉外卖SpringCloud黑马旅游谷粒商城学成在线MySQL高级篇设计模式牛客面试题 目录 8. 优先考虑覆盖索引 8.1 什么是覆盖索引&#xff1f; 8.1.0 概念 8.0.1 覆盖索引情况下&#xff0c;“不等于”…

Fourier分析入门——第4章——频率域

目录 第 4 章 频率域(The Frequency Domain) 4.1 频谱分析(Spectral Analysis) 4.2 物理单位(Physics units) 4.3 笛卡尔坐标形式与极坐标形式对比 4.4 频谱分析的复数形式 4.5 复数值Fourier系数 4.6 复数值的和三角的Fourier系数之间的关系 4.7 2维或多维离散Fouri…

内容好但流量差?B站流量密码可能就在这

B站知名数码UP主老师好我叫何同学&#xff08;以下简称“何同学”。&#xff09;时隔两个月再次更新&#xff0c;这支标题为《为了找到流量密码&#xff0c;我们做了个假B站...》的视频不仅吸引了观众的围观&#xff0c;更是获得了众多B站UP主们的“声援”。 如题所见&#xf…

K8s in Action 阅读笔记——【3】Pods: running containers in Kubernetes

K8s in Action 阅读笔记——【3】Pods: running containers in Kubernetes 3.1 Introducing pods 在Kubernetes中&#xff0c;Pod是基本构建块之一&#xff0c;由容器集合组成。与独立部署容器不同&#xff0c;你总是要部署和操作一个Pod。Pod并不总是包含多个容器&#xff0…

如何高效地在网上找开源项目

开源项目是发展技能、分享想法和成为开发社区一员的好方法。开源意味着软件功能背后的源代码与所有想要阅读它的人公开共享。这意味着你可以准确地看到一个系统是如何工作的——一旦你愿意冒险&#xff0c;就为它做出贡献。除了向所有人开放贡献外&#xff0c;这种开放代码库通…

经典JavaScript手写面试题和答案

文章目录 实现一个函数去重&#xff1f;实现一个函数&#xff0c;判断指定元素在数组中是否存在&#xff1f;实现一个函数&#xff0c;将给定字符串反转&#xff1f;实现一个函数&#xff0c;检测指定字符串是否为回文&#xff08;即从前往后和从后往前的字符序列都相同&#x…

Systrace系列4 —— SystemServer 解读

本文主要是对 SystemServer 进行简单介绍,介绍了 SystemServer 中几个比较重要的线程,由于 Input 和 Binder 比较重要,所以单独拿出来讲,在这里就没有再涉及到。 窗口动画 Systrace 中的 SystemServer 一个比较重要的地方就是窗口动画,由于窗口归 SystemServer 来管,那么…

react学习3 生命周期

componentDidMount()与render()一个级别的&#xff0c;在组件挂载完成之后调用 卸载组件&#xff1a;REACTDOM.unmountComponentAtNode() componentWillUnmount() 组件马上被卸载的时候 老生命周期&#xff1a; 新的生命周期&#xff1a; 废弃了&#xff08;加上Unsate_还是…

RabbitMQ --- 死信交换机(一)

前言 当我们在使用消息队列时&#xff0c;难免会遇到一些消息被拒绝&#xff0c;重复投递或者超时等异常情况。这些异常消息如果不被正确处理&#xff0c;将会阻碍整个消息系统的正常运行。而此时&#xff0c;死信交换机&#xff08;Dead Letter Exchange&#xff0c;简称DLX&…

FAT NTFS Ext3文件系统有什么区别

10 年前 FAT 文件系统还是常见的格式&#xff0c;而现在 Windows 上主要是 NTFS&#xff0c;Linux 上主要是Ext3、Ext4 文件系统。关于这块知识&#xff0c;一般资料只会从支持的磁盘大小、数据保护、文件名等各种维度帮你比较&#xff0c;但是最本质的内容却被一笔带过。它们最…

MySQL-索引(2)

本文主要讲解MySQL-索引相关的知识点 联合索引前缀索引覆盖索引索引下推索引的优缺点什么时候适合创建索引,什么时候不适合?如何优化索引 ? 索引失效场景 ? 为什么SQL语句使用了索引,却还是慢查询 ? 使用索引有哪些注意事项 ? InnoDB引擎中的索引策略 目录 联合索引 联合…

【C++】函数重载 - 给代码增添多彩的魔法

欢迎来到博主 Apeiron 的博客&#xff0c;祝您旅程愉快 &#xff01; 时止则止&#xff0c;时行则行。动静不失其时&#xff0c;其道光明。 目录 1、缘起 2、函数重载概述 3、函数重载注意事项 4、总结 1、缘起 函数重载&#xff0c;是编程世界中的一抹迷人色彩&#xff0c…

动态规划-状态压缩DP

[SCOI2005] 互不侵犯 题目描述 https://www.luogu.com.cn/problem/P1896 在NN的棋盘里面放K个国王&#xff0c;使他们互不攻击&#xff0c;共有多少种摆放方案。国王能攻击到它上下左右&#xff0c;以及左上左下右上右下八个方向上附近的各一个格子&#xff0c;共8个格子。 …

堪比ChatGPT,Claude注册和使用教程

新建了一个网站 https://ai.weoknow.com/ 每天给大家更新可用的国内可用chatGPT资源 Claude简介 Claude是一款人工智能聊天机器人。主要有以下特征: 使用自己的模型与训练方法,而不是基于GPT-3等开源框架。模型采用Transformer编码器与解码器的结构,并使用对话上下文的双向…

实验六 自动驾驶建模与仿真

【实验目的】 了解Matlab/Simulink软件环境&#xff0c;熟悉Simulink建模步骤&#xff1b;了解车辆运动控制的基本原理&#xff0c;学会简单的车辆运动控制建模及仿真&#xff1b;了解自动驾驶建模的基本过程&#xff0c;了解典型ADAS系统模型的应用特点。了解自动驾驶相关函数…

老司机解读香农定理、奈奎斯特定理、编码与调制

工程师都会考虑一个问题&#xff1a;信道上到底可以传输多大的数据&#xff0c;或者指定的信道上的极限传输率是多少。这就是信道容量的问题。例如&#xff0c;在xDSL系统中&#xff0c;我们使用的传输介质是仅有几兆带宽的电话线&#xff0c;而上面要传送几兆、十几兆甚至几十…

用 Python 写 3D 游戏

vizard介绍 Vizard是一款虚拟现实开发平台软件&#xff0c;从开发至今已走过十个年头。它基于C/C&#xff0c;运用新近OpenGL拓展模块开发出的高性能图形引擎。当运用Python语言执行开发时&#xff0c;Vizard同时自动将编写的程式转换为字节码抽象层(LAXMI)&#xff0c;进而运行…

WorkPlus AI助理 | 将企业业务场景与ChatGPT结合

近年来&#xff0c;人工智能成为了企业数字化转型的热门话题&#xff0c;作为被训练的语言模型&#xff0c;ChatGPT具备模拟对话、回答问题、写代码、写小说、进行线上内容创作的能力&#xff0c;还能根据聊天的上下文进行互动。作为一款新兴的人工智能应用程序&#xff0c;对于…

【IDEA】DeBug(图文并茂)

文章目录 01_Debug简介和意义02_IDEA中的Debug步骤03_跳转到当前代码执行的行04_步过调试的使用05_步入调试的使用06_强制步入调试的使用07_步出调试的使用08_回退断点调试的使用09_运行到光标处10_计算表达式11_条件断点12_多线程调试 IDAEA&#xff08;Interactive Data Anal…