Golang 04 包

总篇:32

编辑于 2025/6/20 11:00

截稿于: 2025/6/21 16:20

【2025年新版】Go语言教程_Golang入门实战全套视频教程_哔哩哔哩_bilibili

P19-27

《Go 入门指南》 | Go 技术论坛

第九章

例举:

像 fmt、os 等这样具有常用功能的内置包在 Go 语言中有 150 个以上,它们被称为标准库,大部分 (一些底层的除外) 内置于 Go 本身。

以下列出部分包及其作用:

  • unsafe: 包含了一些打破 Go 语言 “类型安全” 的命令,一般的程序中不会被使用,可用在 C/C++ 程序的调用中。
  • syscall-os-os/exec:
    • os: 提供给我们一个平台无关性的操作系统功能接口,采用类 Unix 设计,隐藏了不同操作系统间差异,让不同的文件系统和操作系统对象表现一致。
    • os/exec: 提供我们运行外部操作系统命令和程序的方式。
    • syscall: 底层的外部包,提供了操作系统底层调用的基本接口。
  • archive/tar 和 /zip-compress:压缩 (解压缩) 文件功能。
  • fmt-io-bufio-path/filepath-flag:
    • fmt: 提供了格式化输入输出功能。
    • io: 提供了基本输入输出功能,大多数是围绕系统功能的封装。
    • bufio: 缓冲输入输出功能的封装。
    • path/filepath: 用来操作在当前系统中的目标文件名路径。
    • flag: 对命令行参数的操作。  
  • strings-strconv-unicode-regexp-bytes:
    • strings: 提供对字符串的操作。
    • strconv: 提供将字符串转换为基础类型的功能。
    • unicode: 为 unicode 型的字符串提供特殊的功能。
    • regexp: 正则表达式功能。
    • bytes: 提供对字符型分片的操作。
  • index/suffixarray: 子字符串快速查询。
  • math-math/cmath-math/big-math/rand-sort:
    • math: 基本的数学函数。
    • math/cmath: 对复数的操作。
    • math/rand: 伪随机数生成。
    • sort: 为数组排序和自定义集合。
    • math/big: 大数的实现和计算。   
  • container-/list-ring-heap: 实现对集合的操作。
    • list: 双链表。
    • ring: 环形链表。
  • time-log:
    • time: 日期和时间的基本操作。
    • log: 记录程序运行时产生的日志,我们将在后面的章节使用它。
  • encoding/json-encoding/xml-text/template:
    • encoding/json: 读取并解码和写入并编码 JSON 数据。
    • encoding/xml: 简单的 XML1.0 解析器。
  • text/template: 生成像 HTML 一样的数据与文本混合的数据驱动模板。
  • net-net/http-html:
    • net: 网络数据的基本操作。
    • http: 提供了一个可扩展的 HTTP 服务器和基础客户端,解析 HTTP 请求和回复。
    • html: HTML5 解析器。
  • runtime: Go 程序运行时的交互操作,例如垃圾回收和协程创建。
  • reflect: 实现通过程序运行时反射,让程序操作任意类型的变量。

锁和sync包

与Java不同,Golang的锁是写在结构体中的,保护共享资源的并发访问,相同的是锁住的是一片代码块区。

Mutex:普通锁,读写都锁,Lock(),UnLock()

RWMutex:读写锁,允许并发读,写时锁,RLock(),UnRlock()

Once.Do(call_func):保证函数只调用一次

package main

import (
    "fmt"
    "sync"
)

type Info struct {
    Str string
    mu  sync.Mutex
}

func Update(info *Info) {
    info.mu.Lock()
    // critical section:
    info.Str = "new value" // new value
    // other code
    fmt.Println("Updating Info.Str to:", info.Str)
    // end critical section
    info.mu.Unlock()
}

func main() {
    var info Info
    info.Str = "initial value"

    // 启动多个 Goroutine 来更新 Info.Str
    var wg sync.WaitGroup
    for i := 0; i < 10; i++ {
        wg.Add(1)
        go func() {
            defer wg.Done()
            Update(&info)
        }()
    }

    wg.Wait()
    fmt.Println("Final Info.Str:", info.Str)
}
 Goroutine:协程、go func:匿名直接执行,暂时还不理解哈。

sync_demo.go:

package pkg

import (
	"fmt"
	"strconv"
	"sync"
	"time"
)

type Info struct {
	Str string
	mu  sync.Mutex
}

func SyncDemo() {
	var info Info
	info.Str = "initial value"

	// 启动多个 Goroutine 来更新 Info.Str
	var wg sync.WaitGroup
	for i := 0; i < 10; i++ {
		wg.Add(1)

		go func() {
			defer wg.Done()
			Update(&info)
		}()
	}
	wg.Wait()
	fmt.Println("Final Info.Str:", info.Str)
}
func Update(info *Info) {
	info.mu.Lock()
	// goroutine执行速度非常快,达到了纳秒级别
	info.Str = "new value" + " " + strconv.FormatInt(time.Now().UnixNano(), 10) 
	// other code
	fmt.Println("Updating Info.Str to:", info.Str)
	// end critical section
	info.mu.Unlock()
}

main.go:

package main

import (
	"day04/pkg"
)

func main() {
	// 调用 pkg 包中的 SyncDemo 函数
	pkg.SyncDemo()
}

一个有用的实践,给bytes.buffer上锁,安全拼接字符串:

type SyncedBuffer struct {
    lock    sync.Mutex
    buffer  bytes.Buffer
}

自定义包

在原生项目目录下,go文件声明的包必须是它所在的目录,导入包是根据其相对路径或网络URL

在idea中,目录结构如下:

-day04
--pkg
---sync_demo.go //package pkg
--go.mod // module day04
--main.go // import "day04/pkg"

文件声明的package是他所在的目录,其他go文件导入的时候从模块名开始导入。

go doc

教程中的godoc -http=:6060 -goroot="." 已废弃,新版本的文档查看命令是go doc :

go doc pkg //直接指定包名

cli方式不是很好看。

go install

go install 主要用于安装 可执行文件(即包含 main 包的程序),而不是用于安装普通的库包。这些可执行文件通常是工具,可以直接在命令行中运行。安装完成后,可执行文件会被放置在 $GOBIN 目录中(默认是 $GOPATH/bin 或~/go/bin)。

不要在工作目录下执行安装,这样将其安装在工作目录下而不是$GOBIN目录,命令行无法识别。

一个格式化工具:

go install mvdan.cc/gofumpt@latest

go get

安装第三方包,通过go.mod模块管理,类似于maven,这个就要安装到工作目录而非全局目录了,最重要的一集.

安装web框架gin为例:

 go get github.com/gin-gonic/gin

gin会安装到项目目录下的pkg目录的mod目录下(还可以安装其他框架,目录同名github而已)

一个gin示例代码:

package main

import (
	"github.com/gin-gonic/gin"
	"net/http"
)

func main() {
	// 创建一个默认的路由引擎
	r := gin.Default()

	// 注册一个 GET 路由,路径为 "/ping"
	r.GET("/ping", func(c *gin.Context) {
		c.JSON(http.StatusOK, gin.H{
			"message": "pong",
		})
	})

	// 启动服务,默认在 0.0.0.0:8080 启动服务
	r.Run()
}

和SpringBoot相比更轻量。

posted on 2025-07-14 00:26  依只  阅读(11)  评论(0)    收藏  举报

导航