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

news2024/11/14 15:30:31

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语言从入门到实战

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

哪个产品功能重要?KANO模型帮你

哪个产品功能重要&#xff1f;KANO模型来帮你 模型工具可以协助思考和系统化改进 KANO模型是小日本一个教授提出 趣讲大白话&#xff1a;往往&#xff0c;怎么思考&#xff0c;比思考什么重要 【趣讲信息科技175期】 **************************** 东京理工大学教授狩野纪昭(No…

【医学图像】图像分割系列.2 (diffusion)

介绍几篇使用diffusion来实现医学图像分割的论文&#xff1a;DARL&#xff08;ICLR2023&#xff09;&#xff0c;MedSegDiff&#xff08;MIDL2023&#xff09;& MedSegDiff-V2&#xff08;arXiv2023&#xff09;&#xff0c;ImgX-DiffSeg&#xff08;arXiv2023&#xff09;…

CTF 2015: Search Engine-fastbin_dup_into_stack

参考&#xff1a; [1]https://gsgx.me/posts/9447-ctf-2015-search-engine-writeup/ [2]https://blog.csdn.net/weixin_38419913/article/details/103238963(掌握利用点&#xff0c;省略各种逆向细节) [3]https://bbs.kanxue.com/thread-267876.htm&#xff08;逆向调试详解&am…

web功能测试方法大全—完整!全面!(纯干货,建议收藏哦~)

本文通过六个部分为大家梳理了web功能测试过程中&#xff0c;容易出现的遗漏的部分&#xff0c;用以发掘自己工作中的疏漏。&#xff08;纯干货&#xff0c;建议收藏哦~&#xff09; 一、输入框 1、字符型输入框 2、数值型输入框 3、日期型输入框 4、信息重复 在一些需要命…

GPT-4版Windows炸场,整个系统就是一个对话机器人,微软开建AI全宇宙

原创 智东西编辑部 智东西 Windows的GPT时刻到来&#xff0c;变革PC行业。 作者 | 智东西编辑部 今日凌晨&#xff0c;Windows迎来了GPT-4时刻&#xff01; 在2023微软Build大会上&#xff0c;微软总裁萨蒂亚纳德拉&#xff08;Satya Nadella&#xff09;宣布推出Windows Co…

实现免杀:Shellcode的AES和XOR加密策略(vt查杀率:4/70)

前言 什么是私钥和公钥 私钥和公钥是密码学中用于实现加密、解密和数字签名等功能的关键组件。 私钥是一种加密算法中的秘密密钥&#xff0c;只有密钥的拥有者可以访问和使用它。私钥通常用于数字签名和数据加密等场景中&#xff0c;它可以用于对数据进行加密&#xff0c;同…

头部效应凸显,消金行业迈入“巨头赛”?

回顾已经过去的2022年&#xff0c;消金行业面临着来自多方面的考验&#xff0c;承压前行&#xff0c;而随着进入2023年&#xff0c;相关企业也陆续展示出过去一年的发展成果&#xff0c;以此为后续发展做出指引。 当前&#xff0c;30家已开业的消金公司中&#xff0c;29家的20…

《消息队列高手课》课程笔记(三)

如何利用事务消息实现分布式事务&#xff1f; 什么是分布式事务&#xff1f; 消息队列中的“事务”&#xff0c;主要解决的是消息生产者和消息消费者的数据一致性问题。如果我们需要对若干数据进行更新操作&#xff0c;为了保证这些数据的完整性和一致性&#xff0c;我们希望…

独立站怎么搭建?搭建一个独立站的10个建议和步骤

要搭建一个独立站&#xff08;也称为个人网站或博客&#xff09;&#xff0c;以下是一些建议和步骤&#xff1a; 选择一个合适的域名&#xff1a;选择一个简洁、易记且与您网站内容相关的域名。确保域名可用&#xff0c;并注册该域名。 寻找一个合适的主机服务提供商&#xff…

【Cpp】哈希之手撕闭散列/开散列

文章目录 unorderedunordered系列关联式容器unordered_map和unordered_set概述unordered_map的文档介绍unordered_map的接口说明 底层结构 哈希哈希/散列表 概念哈希冲突哈希函数哈希函数设计原则&#xff1a;常见哈希函数 哈希冲突解决闭散列线性探测二次探测 开散列 哈希表的…

C语言数据结构——树、堆(堆排序)、TOPK问题

&#x1f436;博主主页&#xff1a;ᰔᩚ. 一怀明月ꦿ ❤️‍&#x1f525;专栏系列&#xff1a;线性代数&#xff0c;C初学者入门训练&#xff0c;题解C&#xff0c;C的使用文章&#xff0c;「初学」C&#xff0c;数据结构 &#x1f525;座右铭&#xff1a;“不要等到什么都没…

使用go语言构建区块链 Part4.事务1

英文源地址 简介 事务是比特币的核心, 区块链的唯一目的是以安全可靠的方式存储交易, 因此在交易创建后没有人可以修改. 今天我们开始实现事务, 但由于这是一个相当大的主题, 我将它分成两部分: 在这一部分中, 我们将实现事务的通用机制, 在第二部分中, 我们将研究细节. 此外…

让你在Windows打开Sketch格式再也不愁

Sketch是Macos的专用矢量绘图应用。在Sketch软件中&#xff0c;ios开发者可以轻松设计图层面板等图层的常用操作&#xff0c;广泛应用于产品的交互设计和UI设计&#xff0c;帮助很多设计师创作出很多优秀的作品。然而&#xff0c;Sketch只服务于Macos系统&#xff0c;这使得许多…

Laravel框架06:文件、迁移填充、会话、缓存

Laravel框架06&#xff1a;文件、迁移填充、会话、缓存 一、文件上传1. 文件上传表单2. 上传业务处理3. 全部代码 二、数据表的迁移与填充1. 迁移文件① 创建迁移文件② 编写迁移文件③ 执行迁移文件④ 回滚迁移文件 2. 填充&#xff08;种子&#xff09;文件① 创建填充文件②…

C++常用的支持中文的GUI库Qt 6之三: Qt 6的项目的发布

C常用的支持中文的GUI库Qt 6之三&#xff1a; Qt 6的项目的发布 本文接着上一篇“C常用的支持中文的GUI库Qt 6之二&#xff1a;项目的结构、资源文件的使用” https://blog.csdn.net/cnds123/article/details/130741807介绍&#xff0c;并使用其中的例子。 程序代码能正确编译…

【STL】list的使用

系列文章 学习C途中自然绕不过STL&#xff0c;在这个系列文章之中 我们讲了string的使用和string的模拟实现&#xff0c;以及vector的使用、vector的模拟实现。 感兴趣的可以翻翻看。 目录 系列文章 前言 默认成员函数 构造函数 拷贝构造 赋值重载 迭代器 容量查询 …

人人都能看懂的Spring源码解析,Spring声明式事务关于传播特性、事务挂起与恢复的处理

人人都能看懂的Spring源码解析&#xff0c;Spring声明式事务关于传播特性、事务挂起与恢复的处理 原理解析AbstractPlatformTransactionManager事务传播特性事务挂起与恢复通过DataSourceTransactionManager看事务挂起和恢复的具体实现 代码走读总结 往期文章&#xff1a; 人人…

LRU Cache

前言 哈喽&#xff0c;各位小伙伴大家好&#xff0c;本章内容为大家介绍计算机当中为了提高数据相互传输时的效率而引进的一种重要设计结构叫做LRU Cache,下面将为大家详细介绍什么是LRU Cache,以及它是如何是实现的&#xff0c;如何提升效率的。 1.什么是LRU Cache? LRU是L…

卷起来了?2023这三个项目直接让你原地起飞!

理论自学谁不会&#xff0c;理论知识跟实战项目实践相结合才是大问题&#xff1f; 还在发愁没有项目练手&#xff1f;还在发愁简历中的项目生搬硬凑&#xff1f;还在担心自己没实操过项目被面试官直接K.O? 这三个实战项目让你快人一步&#xff0c;总有一个适合你的&#xff…

数慧时空20年磨一剑:推出智能遥感云平台DIEY,自然资源多模态大模型“长城”,为地理信息产业提速

作者 | 伍杏玲 出品 | CSDN 据中国地理信息产业发展报告公布的数据&#xff0c;截至2020年末&#xff0c;行业从业单位13.8万家&#xff0c;从业人数336.6万&#xff0c;到2021年末&#xff0c;从业单位增加到16.4万家&#xff0c;从业人数增加到398万&#xff0c;产业规模越…