首页 > 其他分享 >Golang学习笔记(1):包管理

Golang学习笔记(1):包管理

时间:2024-06-06 23:21:53浏览次数:16  
标签:学习 package 笔记 Golang go main mypkg mod

Golang学习笔记(1):包管理

本人学习Golang主要是为了做MIT6.824的lab,然而一上来就被Golang神奇的import搞混了,因此写一篇博客记录学习Golang的包管理的过程。

package main

import "fmt"

func main() {
    fmt.Println("hello, world")
}

如果有编程基础肯定会觉得这段代码很好理解,它可以在终端输入hello,world并自动换行。但如果深究这段代码里的细节我们可以提出很多有价值的问题。

  • package main 是什么意思?
  • fmt 也是一个package吗?
  • 如果把func作为main函数的关键词提示,那么它返回什么,传入什么?这在Golang里该如何表示?

本篇文章主要解决关于package的问题,因为这个问题在根本上和博主熟知的C语言不一样,他们的区别绝对不是includeimport 不同写法的区别。

首先展示一下我把importinclude用遇到的问题

文件目录:

.
├── main.go
└── pkg_va.go

1 directory, 2 files

main.go

package main

import (
        "fmt"
        "mypkg"
)

func main() {
        fmt.Println(mypkg.I)
}

pkg_var.go

package mypkg

var I int

func init() {
        I = 10
}

按我的想法我把mypkg包括进来了就应该能用mypkg相关文件里的值了。

然而却遇到了这样的问题

xiongzile@LAPTOP-S6FR5EAE:~/workspace/demo/go$ go run main.go
main.go:5:2: package mypkg is not in std (/usr/lib/go-1.22/src/mypkg)

这段报错说是系统中找不到我的包,如果你对C语言很熟悉你就会想到这是

#include <xxx.h>

而这个xx.h是你自己定义的头文件会出现的错误。

那我们有没有类似

#include "xxx.h"

的表达呢?

很遗憾Golang似乎是没有的,发现了这一点我就明白了学C的我对包管理还是一窍不通的状态,所以我要开始学习Golang的包管理了!

早期Golang的包管理很简单粗暴, 有一个GOPATH环境变量, 系统识别包路径不仅会识别std里的,还会识别这个环境变量对应的路径下的。 这会导致开发者创建项目是不自由的,随时要改GOPATH环境变量,我认为没人想每次换路径都改环境变量。

Golang认识到这一点之后推出了Modules包管理,也就是现在的Go开发者真正需要学习了解的,也是这篇博客的重点。

回到刚才那个问题,我们如何用Go Modules来管理外部库(我们自己写的库或者在网上找的别人写的库)的依赖?

首先要在项目根目录下启动我们自己的Go模块:

go mod init yourmodulename

效果如下:

xiongzile@LAPTOP-S6FR5EAE:~/workspace/demo/go$ go mod init mymod
go: creating new go.mod: module mymod
go: to add module requirements and sums:
        go mod tidy

这样我们就有了一个自己的模板,我们可以在这里自由的导入或者移除外部库

修改一下main.go代码

package main

import (
        "fmt"
        "mymod/mypkg"
)

func main() {
        fmt.Println(mypkg.I)
}

这样是不是就可以了呢?

xiongzile@LAPTOP-S6FR5EAE:~/workspace/demo/go$ go run main.go
main.go:5:9: package mymod/mypkg is not in std (/usr/lib/go-1.22/src/mymod/mypkg)

答案是依旧不行,因为Golang规定导入包必须满足如下类似目录结构,请参考:

.
├── go.mod
├── main.go
└── mypkg
    └── pkg_va.go

2 directories, 3 files
xiongzile@LAPTOP-S6FR5EAE:~/workspace/demo/go$ go run main.go
10

现在终于可以啦!我们注意到使用了这个指令之后,我们的工程目录下多了一个文件go.mod

我们看一下里面包括什么内容:

 module mymod

 go 1.22.2

目前这个文件只包括了我们的module名和我们使用的go版本号。在我们尝试使用外部库的时候会出现更多内容。

接下来看一个代码示例:

// main.go
package main
import (
    "github.com/gorilla/mux"
    "log"
    "net/http"
    "os"
)
func homeHandler(w http.ResponseWriter, r *http.Request) {
    log.Println("处理首页请求")
    w.WriteHeader(http.StatusOK)
    w.Write([]byte("欢迎来到Go Modules Web服务!"))
}
func main() {
    // 使用环境变量或默认值设置日志文件
    logFile, err := os.OpenFile(os.Getenv("LOG_FILE_PATH"), os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0666)
    if err != nil {
        log.Fatal("打开日志文件失败:", err)
    }
    defer logFile.Close()
    // 设置日志输出
    log.SetOutput(logFile)
    r := mux.NewRouter()
    r.HandleFunc("/", homeHandler)
    log.Println("启动Web服务:localhost:8080")
    if err := http.ListenAndServe(":8080", r); err != nil {
        log.Fatal("启动Web服务失败:", err)
    }
}

我们尝试运行,得到了这样的结果:

xiongzile@LAPTOP-S6FR5EAE:~/workspace/demo/go$ go run main.go
main.go:4:5: no required module provides package github.com/gorilla/mux; to add it:
        go get github.com/gorilla/mux

我们按照go的提示输入go get github.com/gorilla/mux

再次查看go.mod

module mymod

go 1.22.2

require github.com/gorilla/mux v1.8.1

多了一个require 关键词,结合我们刚才的操作不难理解,这个关键词是为了让我们获取外部库,并能在这个项目中运用。

到目前为止,我们就能够在我们的项目里实现对外部库和我们自己的库的调用了,接下来提供几个常用的关于go module管理的指令。

go mod init + modulename : 初始化模块,并为当前模块命名。

go mod tidy: 管理包,增加本地缺失的包,删除没用的包。

go mod graph: 查看模块间依赖图

学到这里应该就能进行基本的包管理(目前是够用了),进阶的以后再慢慢学。

博主是Golang的初学者,如果有任何错误欢迎提醒我。

博主邮箱

[email protected]

参考资料

https://developer.aliyun.com/article/1486997?spm=5176.26934562.main.6.215e4a0aZRNBnS

标签:学习,package,笔记,Golang,go,main,mypkg,mod
From: https://www.cnblogs.com/Luvm/p/18236277

相关文章

  • 微信小程序学习总结——①
    一、小程序代码的构成1.了解项目的基本组成结构①pages用来存放所有小程序的页面②utils用来存放工具性质的模块(例如:格式化时间的自定义模块)③app.js小程序项目的入口文件④app.json小程序项目的全局配置文件,包括了小程序的所有页面路径、窗口外观、界面表现、底......
  • 微信小程序学习总结——③
    三、小程序的视图与逻辑1.页面导航①页面导航指的是页面之间的相互跳转。例如,浏览器中实现页面导航的方式有如下两种:Ⅰ.<a>链接Ⅱ.location.href②小程序中实现页面导航的两种方式Ⅰ.声明式导航。在页面上声明一个<navigator>导航组件通过点击<navigator>组件......
  • 工作笔记(8)
    Program.cs启用OpenAPI支持:(Swagger支持)顶级语句:使用控制器:miniAPIHTTP与HTTPS的区别1.HTTPS协议需要到CA申请证书,一般免费的证书比较少,因而需要一定费用。2.HTTP是超文本传输协议,信息是明文传输,HTTPS则是具有安全性的SSL加密传输协议。3.HTTP和HTTPS使用的是完全不同的链......
  • 工作笔记(7)
    SQL事务begintransactiondemo--开始事务+事务名 begintry insertinto[User]values('tianqi','123456','田七','false','2001-09-22','','0','false',NULL,'false') insertin......
  • 大模型学习笔记-汇总篇
    本文记录一下最近一个月学习的大模型相关的技术知识点,为拥抱AI浪潮做些技术储备。大模型术语相关参数规模GPT3.5千亿级别GPT41.8W亿级别国内一般都是十亿或百亿级别ChatGLM2_2K_6BBAICHUAN_4K_13B淘宝星辰_4K_13BTOKEN长度Token是指被LLM处理的离散的数据单......
  • 工作笔记(6)
    快捷键替换选中内容:Ctrl+HCtrl+Alt+Enter退出终端:Ctrl+Cvue初始化格式:Vueinit设置路由:router/index/js{path:"/studentInfo",name:"studentInfo",component:()=>import("../views/Student/StudentView.vue")}布局页:APP.vueEmmit语法......
  • 工作笔记(10)
    SignalR微软官方文档TMS关键字:大车GPS交通局短信休息15分钟/4小时火星坐标=>大地坐标(如果要用百度地图还要将大地坐标=>百度坐标)电子围栏①模拟制造数据(预制路线):C/S架构1条/5秒非关系型数据库/时序数据库 17280条/日/车SignalR:长连接 API主动同步数据到客户端案例......
  • golang select 的 case 执行顺序
    问题:golangselect结构,假如底下有三个case,分别从chan1,chan2,chan3读取内容,chan1,chan2,chan3都是非阻塞的,那么是会先进入第一个case,其它case还会再进入吗?在Go语言中,select语句用于监控多个通道的操作,并在其中一个操作准备好时执行相应的case。如果多个case同......
  • 数据结构学习笔记-归并排序
    归并排序算法的设计与分析问题描述:设计并分析归并排序算法【算法设计思想】分割(Divide):从中间分割数组,使每个子数组包含一半的元素。这通过计算中点m来完成,通常是(l+r)/2,但为了防止大数溢出,使用l+(r-l)/2。解决(Conquer):递归地对两个子数组应用归并排序,直到......
  • 运筹学习题Python精解——线性规划
    题1某企业有三个车间生产同一种产品。每件产品由四个零件1和三个零件2组成。两个零件需耗用两种原材料A和B。已知这两种原材料的供应量分别为300kg和500kg。由于三个车间拥有的设备及工艺条件不同,每个工班原材料耗用量和零件产量也不同。见下表(三个车间每班用料和生产......