Go语言学习笔记(三)

这篇具有很好参考价值的文章主要介绍了Go语言学习笔记(三)。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

教程:文档 - Go 编程语言 (studygolang.com)

调用模块代码

在call-module-code需要注意,需要在hello目录下操作

go mod edit -replace example.com/greetings=../greetings

这是一个在Go项目的模块管理中的命令。在Go的模块管理工具(go mod)中,这个命令用于修改模块依赖关系。

具体来说,go mod edit -replace example.com/greetings=../greetings 这个命令的作用是:

  1. -replace: 这个选项表示你要替换一个已经存在的依赖。
  2. example.com/greetings: 这是你要替换的依赖的原始路径。
  3. ../greetings: 这是你要替换成的新路径。

所以,这个命令的意思是:将example.com/greetings这个依赖替换为项目根目录下的greetings目录。

简单来说,这个命令用于将一个远程依赖替换为本地路径的依赖。这在你想要使用本地版本的库而不是远程版本时非常有用,例如在开发过程中。

go mod tidy

go mod tidy 是一个 Go 语言的命令,用于自动添加或删除不必要的模块依赖项,使 go.mod 文件保持最新。

当你使用 Go 语言开发一个项目时,可能会使用 go get 命令来获取外部的依赖库。这些库会被添加到项目的 go.mod 文件中。随着时间的推移,有些依赖可能不再需要,或者新的依赖可能被添加进来。为了保持 go.mod 文件的整洁和一致性,你可以使用 go mod tidy 命令来自动处理这些不必要的依赖。

具体来说,go mod tidy 会做以下几件事:

  1. 删除不必要的依赖:如果一个依赖在代码中没有被使用,或者其版本与 go.mod 文件中指定的版本不匹配,那么这个依赖会被从 go.mod 文件中移除。
  2. 添加缺失的依赖:如果代码中使用了某个外部库,但这个库还没有被添加到 go.mod 文件中,那么 go mod tidy 会自动将其添加进来。
  3. 更新依赖的版本:如果某个依赖有新版本可用,并且这个新版本与 go.mod 文件中指定的版本不匹配,那么 go mod tidy 会自动更新这个依赖的版本。

总之,go mod tidy 是一个非常有用的命令,可以帮助开发者自动管理项目的模块依赖,确保 go.mod 文件始终是最新的。

 操作后hello文件夹下go.mod内容为

Go语言学习笔记(三),Go,学习,笔记

 如果不操作,则报错hello.go:6:2: no required module provides package example.com/greetings; to add it:
        go get example.com/greetingsGo语言学习笔记(三),Go,学习,笔记

处理错误

package greetings

import (
	"errors"
	"fmt"
)

// Hello returns a greeting for the named person.
func Hello(name string) (string, error) {
	if name == "" {
		return "", errors.New("empty name")
	}
	// Return a greeting that embeds the name in a message.
	message := fmt.Sprintf("Hi, %v. Welcome!", name)
	return message, nil
}
package main

import (
	"fmt"
	"log"

	"example.com/greetings"
)

func main() {
	// Get a greeting message and print it.
	message, err := greetings.Hello("")
	if err != nil {
		log.Fatal(err)
	}
	fmt.Println(message)
}

使用日志

package main

import (
	"fmt"
	"log"

	"example.com/greetings"
)

func main() {
	log.SetPrefix("greetings: ")
	log.SetFlags(0)
	// Get a greeting message and print it.
	message, err := greetings.Hello("")
	if err != nil {
		log.Fatal(err)
	}
	fmt.Println(message)
}

返回随机问候语

package main

import (
	"errors"
	"fmt"
	"log"
	"math/rand"
	// "example.com/greetings"
)

func Hello(name string) (string, error) {
	if name == "" {
		return name, errors.New("Empty name")
	}
	message := fmt.Sprintf(randomFormat(), name)
	return message, nil
}
func randomFormat() string {
	stringArray := []string{"Hi, %v. Welcome!",
		"Great to see you, %v!",
		"Hail, %v! Well met!"}
	index := rand.Intn(len(stringArray))
	return stringArray[index]
}
func main() {

	message, err := Hello("小明")
	if err != nil {
		log.Fatal(err)
	}
	fmt.Println(message)
}

向多人问候

package greetings

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

func Hello(name string) (string, error) {
	if name == "" {
		return name, errors.New("Empty name")
	}
	message := fmt.Sprintf(randomFormat(), name)
	return message, nil
}
func randomFormat() string {
	stringArray := []string{"Hi, %v. Welcome!",
		"Great to see you, %v!",
		"Hail, %v! Well met!"}
	index := rand.Intn(len(stringArray))
	return stringArray[index]
}
func Hellos(names []string) (map[string]string, error) {
	cMap := make(map[string]string)
	for _, value := range names {
		message, err := Hello(value)
		if err != nil {
			return nil, err
		}
		cMap[value] = message
	}
	return cMap, nil

}

知识点:

1、函数入参为数组怎么写。

2、函数返回值为map怎么写

3、如何创建一个map   make(map[string]string)

package main

import (
	"fmt"
	"log"

	"example.com/greetings"
	// "example.com/greetings"
)

func main() {
	names := []string{
		"小明",
		"小王",
	}
	message, err := greetings.Hellos(names)
	if err != nil {
		log.Fatal(err)
	}
	fmt.Println(message)
}

添加单元测试

package greetings

import (
	"regexp"
	"testing"
)

func TestHelloName(t *testing.T) {
	name := "Gladys"
	want := regexp.MustCompile(`\b` + name + `\b`)
	msg, err := Hello("Gladys")
	if !want.MatchString(msg) || err != nil {
		t.Fatalf(`Hello("Gladys")=%q,%v,want match for %#q,nil`, msg, err, want)

	}

}
func TestHelloEmpty(t *testing.T) {
	msg, err := Hello("")
	if msg != "" || err == nil {
		t.Fatalf(`Hello("") = %q, %v, want "", error`, msg, err)
	}

}

名为TestHelloName的测试函数,它接受一个类型为*testing.T的参数t。这是Go语言中用于编写测试的标准方式。 

TestHelloName方法若msg中不存在name或者err不为nil,则用例失败,

Go语言学习笔记(三),Go,学习,笔记

在vscode中,可以在测试函数前点击运行按钮运行,也可以在命令行运行go test或者 go test -v

 编译和安装应用程序

代码编译为可执行文件,生成hello.exe

go build

Go语言学习笔记(三),Go,学习,笔记

命令行下运行hello.exe

Go语言学习笔记(三),Go,学习,笔记 安装软件包

go install

Go语言学习笔记(三),Go,学习,笔记

A Tour of Go 

 这个tour教程不错。

左边为教程,右边为实例

Go语言学习笔记(三),Go,学习,笔记

指针

Go 拥有指针。指针保存了值的内存地址。

类型 *T 是指向 T 类型值的指针。其零值为 nil

var p *int

& 操作符会生成一个指向其操作数的指针。

i := 42
p = &i

Go语言学习笔记(三),Go,学习,笔记

* 操作符表示指针指向的底层值。

fmt.Println(*p) // 通过指针 p 读取 i
*p = 21         // 通过指针 p 设置 i

这也就是通常所说的“间接引用”或“重定向”。

与 C 不同,Go 没有指针运算。

package main

import "fmt"

func main() {
	i, j := 42, 2701

	p := &i         // 指向 i
  fmt.Println(p)
	fmt.Println(*p) // 通过指针读取 i 的值
	*p = 21         // 通过指针设置 i 的值
	fmt.Println(i)  // 查看 i 的值

	p = &j         // 指向 j
	*p = *p / 37   // 通过指针对 j 进行除法运算
	fmt.Println(j) // 查看 j 的值
}

 Go语言学习笔记(三),Go,学习,笔记

结构体

一个结构体(struct)就是一组字段(field)。

package main

import "fmt"

type Vertex struct {
	X int
	Y int
}

func main() {
	fmt.Println(Vertex{1, 2})
}

 

结构体字段

结构体字段使用点号来访问。

package main

import "fmt"

type Vertex struct {
	X int
	Y int
}

func main() {
	v := Vertex{1, 2}
	v.X = 4
	fmt.Println(v.X)
}

结构体指针

结构体字段可以通过结构体指针来访问。

如果我们有一个指向结构体的指针 p,那么可以通过 (*p).X 来访问其字段 X。不过这么写太啰嗦了,所以语言也允许我们使用隐式间接引用,直接写 p.X 就可以。

package main

import "fmt"

type Vertex struct {
	X int
	Y int
}

func main() {
	v := Vertex{1, 2}
	p := &v
	p.X = 1e9 //赋值 或者 (*p).X = 1e9 两种写法一样
	fmt.Println(v)
}

输出 

{1000000000 2}

结构体文法

结构体文法通过直接列出字段的值来新分配一个结构体。

使用 Name: 语法可以仅列出部分字段。(字段名的顺序无关。)

特殊的前缀 & 返回一个指向结构体的指针。

 

package main

import "fmt"

type Vertex struct {
	X, Y int
}

var (
	v1 = Vertex{1, 2}  // 创建一个 Vertex 类型的结构体
	v2 = Vertex{X: 1}  // Y:0 被隐式地赋予
	v3 = Vertex{}      // X:0 Y:0
	p  = &Vertex{1, 2} // 创建一个 *Vertex 类型的结构体(指针)
)

func main() {
	fmt.Println(v1, p, v2, v3)
}

Go语言学习笔记(三),Go,学习,笔记

数组

类型 [n]T 表示拥有 n 个 T 类型的值的数组。

表达式

var a [10]int

会将变量 a 声明为拥有 10 个整数的数组。

数组的长度是其类型的一部分,因此数组不能改变大小。这看起来是个限制,不过没关系,Go 提供了更加便利的方式来使用数组。

package main

import "fmt"

func main() {
	var a [2]string
	a[0] = "Hello"
	a[1] = "World"
	fmt.Println(a[0], a[1])
	fmt.Println(a)

	primes := [6]int{2, 3, 5, 7, 11, 13}
	fmt.Println(primes)
}

 

切片

每个数组的大小都是固定的。而切片则为数组元素提供动态大小的、灵活的视角。在实践中,切片比数组更常用。

类型 []T 表示一个元素类型为 T 的切片。

切片通过两个下标来界定,即一个上界和一个下界,二者以冒号分隔:

a[low : high]

它会选择一个半开区间,包括第一个元素,但排除最后一个元素。

以下表达式创建了一个切片,它包含 a 中下标从 1 到 3 的元素:

a[1:4]
package main

import "fmt"

func main() {
	primes := [6]int{2, 3, 5, 7, 11, 13}

	var s []int = primes[1:4]
	fmt.Println(s)
}

切片就像数组的引用

切片并不存储任何数据,它只是描述了底层数组中的一段。

更改切片的元素会修改其底层数组中对应的元素。

与它共享底层数组的切片都会观测到这些修改。

package main

import "fmt"

func main() {
	names := [4]string{
		"John",
		"Paul",
		"George",
		"Ringo",
	}
	fmt.Println(names)

	a := names[0:2]
	b := names[1:3]
	fmt.Println(a, b)

	b[0] = "XXX"
	fmt.Println(a, b)
	fmt.Println(names)
}

Go语言学习笔记(三),Go,学习,笔记

修改b的第一个值,切片a和数组中该值都被更改。 

切片文法

切片文法类似于没有长度的数组文法。

这是一个数组文法:

[3]bool{true, true, false}

下面这样则会创建一个和上面相同的数组,然后构建一个引用了它的切片:

[]bool{true, true, false}
package main

import "fmt"

func main() {
	q := []int{2, 3, 5, 7, 11, 13}
	fmt.Println(q)

	r := []bool{true, false, true, true, false, true}
	fmt.Println(r)

	s := []struct {
		i int
		b bool
	}{
		{2, true},
		{3, false},
		{5, true},
		{7, true},
		{11, false},
		{13, true},
	}
	fmt.Println(s)
}

Go语言学习笔记(三),Go,学习,笔记 

切片的默认行为

在进行切片时,你可以利用它的默认行为来忽略上下界。

切片下界的默认值为 0,上界则是该切片的长度。

对于数组

var a [10]int

来说,以下切片是等价的:

a[0:10]
a[:10]
a[0:]
a[:]
package main

import "fmt"

func main() {
	s := []int{2, 3, 5, 7, 11, 13}

	s = s[1:4]
	fmt.Println(s)

	s = s[:2]
	fmt.Println(s)

	s = s[1:]
	fmt.Println(s)
}

切片的长度与容量

切片拥有 长度 和 容量

切片的长度就是它所包含的元素个数。

切片的容量是从它的第一个元素开始数,到其底层数组元素末尾的个数。

切片 s 的长度和容量可通过表达式 len(s) 和 cap(s) 来获取。

你可以通过重新切片来扩展一个切片,给它提供足够的容量。试着修改示例程序中的切片操作,向外扩展它的容量,看看会发生什么。

package main

import "fmt"

func main() {
	s := []int{2, 3, 5, 7, 11, 13}
	printSlice(s)

	// 截取切片使其长度为 0
	s = s[:0]
	printSlice(s)

	// 拓展其长度
	s = s[:4]
	printSlice(s)

	// 舍弃前两个值
	s = s[2:]
	printSlice(s)
}

func printSlice(s []int) {
	fmt.Printf("len=%d cap=%d %v\n", len(s), cap(s), s)
}
len=6 cap=6 [2 3 5 7 11 13]
len=0 cap=6 []
len=4 cap=6 [2 3 5 7]
len=2 cap=4 [5 7]

nil 切片

切片的零值是 nil

nil 切片的长度和容量为 0 且没有底层数组。

package main

import "fmt"

func main() {
	var s []int
	fmt.Println(s, len(s), cap(s))
	if s == nil {
		fmt.Println("nil!")
	}
}

 

[] 0 0
nil!

Go 语言之旅 (go-zh.org) 文章来源地址https://www.toymoban.com/news/detail-787085.html

到了这里,关于Go语言学习笔记(三)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • go语言学习笔记1

    ​ GoLang是一种静态强类型、编译型、并发型,并具有 垃圾回收 功能的编程语言;它可以在不损失应用程序性能的情况下极大的降低代码的复杂性,还可以发挥多核处理器同步多工的优点,并可解决面向对象程序设计的麻烦,并帮助程序设计师处理琐碎但重要的内存管理问题

    2024年02月12日
    浏览(34)
  • Go语言学习笔记(三)

    教程:文档 - Go 编程语言 (studygolang.com) 在call-module-code需要注意,需要在hello目录下操作 这是一个在Go项目的模块管理中的命令。在Go的模块管理工具( go mod )中,这个命令用于修改模块依赖关系。 具体来说, go mod edit -replace example.com/greetings=../greetings  这个命令的作用是:

    2024年02月02日
    浏览(33)
  • Go语言学习笔记(狂神说)

    视频地址:https://www.bilibili.com/video/BV1ae41157o9 聊聊Go语言的历史-KuangStudy-文章 下面列举的是原生使用Go语言进行开发的部分项目。 Docker Docker 是一种操作系统层面的虚拟化技术,可以在操作系统和应用程序之间进行隔离,也可以称之为容器。Docker 可以在一台物理服务器上快速

    2024年02月15日
    浏览(30)
  • 《Go 语言第一课》课程学习笔记(五)

    Go 语言中有一个特殊的函数:main 包中的 main 函数,也就是 main.main,它是所有 Go 可执行程序的用户层执行逻辑的入口函数。 Go 程序在用户层面的执行逻辑,会在这个函数内按照它的调用顺序展开。 main 函数的函数原型非常简单,没有参数也没有返回值。 Go 语言要求:可执行

    2024年02月12日
    浏览(32)
  • 《Go 语言第一课》课程学习笔记(十三)

    Go 语言从设计伊始,就不支持经典的面向对象语法元素,比如类、对象、继承,等等,但 Go 语言仍保留了名为“方法(method)”的语法元素。当然,Go 语言中的方法和面向对象中的方法并不是一样的。Go 引入方法这一元素,并不是要支持面向对象编程范式,而是 Go 践行组合

    2024年02月10日
    浏览(28)
  • 《Go 语言第一课》课程学习笔记(二)

    在 Go 语言中编写一个可以打印出“hello,world”的示例程序,我们只需要简单两步,一是创建文件夹,二是开始编写和运行。 通常来说,Go 不会限制我们存储代码的位置,建议创建一个可以集合所有项目的根文件夹(比如:~/goprojects),然后将所有的项目都放在里面。 对于

    2024年02月12日
    浏览(31)
  • 《Go 语言第一课》课程学习笔记(八)

    Go 语言的类型大体可分为基本数据类型、复合数据类型和接口类型这三种。 其中,我们日常 Go 编码中使用最多的就是基本数据类型,而基本数据类型中使用占比最大的又是数值类型。 Go 语言的整型,主要用来表示现实世界中整型数量等。它可以分为平台无关整型和平台相关

    2024年02月12日
    浏览(36)
  • 《Go 语言第一课》课程学习笔记(十二)

    在 Go 语言中,函数是唯一一种基于特定输入,实现特定任务并可返回任务执行结果的代码块(Go 语言中的方法本质上也是函数)。 在 Go 中,我们定义一个函数的最常用方式就是使用函数声明。 第一部分是 func,Go 函数声明必须以 func 开始。 第二部分是函数名。

    2024年02月11日
    浏览(35)
  • 《Go 语言第一课》课程学习笔记(九)

    Go 语言在常量方面的创新包括下面这几点: 支持无类型常量; 支持隐式自动转型; 可用于实现枚举。 Go 语言的常量是一种在源码编译期间被创建的语法元素。这是在说这个元素的值可以像变量那样被初始化,但它的初始化表达式必须是在编译期间可以求出值来的。 Go 常量

    2024年02月12日
    浏览(31)
  • 《Go 语言第一课》课程学习笔记(十一)

    针对程序的分支结构,Go 提供了 if 和 switch-case 两种语句形式;而针对循环结构,Go 只保留了 for 这一种循环语句形式。 if 语句 if 语句是 Go 语言中提供的一种分支控制结构,它也是 Go 中最常用、最简单的分支控制结构。它会根据布尔表达式的值,在两个分支中选择一个执行

    2024年02月11日
    浏览(37)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包