手把手教你基于gin从零搭建一个属于你自己的go项目(一)

9,670 阅读8分钟

一、为什么写这个,适合什么人看

原因

因为自己想写点小玩意,本来是打算用egg.js来写服务端的,后来发现了个更好玩的midway,但是后来发现自己手上的服务器都是一核2g的小水管,用node有点难顶,于是乎决定用其他技术栈来解决问题,在kotlin和go中初步调研之后发现go更符合自己的需求,于是乎就有了这个系列的笔记输出。

适合食用人群

  1. 对go技术栈或者后端的套路没有什么了解的小白
  2. 想搞点小玩意的前端同学
  3. node已经不满足欲望的前端同学
  4. 想要学习一下从0搭建一个项目的新手同学

不适合食用人群

  1. 无编程基础纯小白
  2. go大佬
  3. 后端大佬

预期内容

大概会有十来篇,打算写成一个适合自己用的通用模版,后期可快速进行crud。

当前发的内容都只是初始版本,等所有内容写完后会进行精修和增删,以便更好食用。

仅限于单体应用,想搞微服务可以了解一下b站开源的kratos框架或者istio

二、如何安装go

(1) 下载

1、下载go是一件非常简单的事情,如果是windows或mac,我们可以直接去官网下载自己需要的版本,然后按指引安装就可以了。

官网地址:golang.org/dl/

image.png

(2) 配置环境变量

1、windows

1.1 系统变量

安装完成后,在系统变量的Path一栏,会自动配置Go语言的GOROOT变量,值为C:\Go\bin。一般情况下,系统变量不需要修改。

1.2 用户变量

在用户变量一栏,会自动配置一个GOPATH变量,默认值为%USERPROFILE%\go,而且在用户变量的Path里会自动配置%USERPROFILE%\bin。这个GOPATH就是我们的工作目录,如果你不希望使用默认路径,可以将其进行修改,例如:

  1. 创建自己想要的目录,并在此目录下,创建三个子文件夹,分别为bin、pkg、src
  2. 编辑GOPATH,将%USERPROFILE%\go值改为自定义的目录
  3. 编辑用户变量的Path,将%USERPROFILE%\bin修改为%GOPATH%\bin。

2、MAC

1.1 bash

  1. 打开 .bash_profile,我们可以在终端输入open ~/.bash_profile 或者 vim ~/.bash_profile 对该文件进行编辑

image.png

  1. 添加配置,在配置文件末尾添加

    export GOPATH=$HOME/go

    export GOBIN=$GOPATH/bin

    export PATH=PATH:PATH:GOBIN

image.png

  1. 最后 source ~/.bash_profile 重载配置

  2. 使用go env查看是否修改

2.2 zsh

mac的默认shell是zsh,所以修改bash的配置文件还是不够的,这时候我们就要根据上面的操作打开zsh的配置文件再来一次

  1. 打开 .zshrc,我们可以在终端输入open ~/.zshrc 或者 vim ~/.zshrc 对该文件进行编辑

  2. 添加配置,在配置文件末尾添加

    export GOPATH=$HOME/go
    export GOBIN=$GOPATH/bin
    export PATH=$PATH:$GOBIN
    
  3. 最后 source ~/.zshrc 重载配置

  4. 使用go env查看是否修改

3、更改Go镜像,启用go mod

go env -w GO111MODULE=on
go env -w GOPROXY=https://goproxy.cn,direct

3.1 什么是go.mod? Go.mod是Golang1.11版本新引入的官方包管理工具用于解决之前没有地方记录依赖包具体版本的问题,方便依赖包的管理。

Go.mod其实就是一个Modules,关于Modules的官方定义为:

Modules是相关Go包的集合,是源代码交换和版本控制的单元。go命令直接支持使用Modules,包括记录和解析对其他模块的依赖性。Modules替换旧的基于GOPATH的方法,来指定使用哪些源文件。

Modules和传统的GOPATH不同,不需要包含例如src,bin这样的子目录,一个源代码目录甚至是空目录都可以作为Modules,只要其中包含有go.mod文件。

3.2 GO111MODULE 参数

  1. GO111MODULE=off,go命令行将不会支持module功能,寻找依赖包的方式将会沿用旧版本那种通过vendor目录或者GOPATH模式来查找。

  2. GO111MODULE=on,go命令行会使用modules,而一点也不会去GOPATH目录下查找。

  3. GO111MODULE=auto,默认值,go命令行将会根据当前目录来决定是否启用module功能。这种情况下可以分为两种情形:

    (1) 当前目录在GOPATH/src之外且该目录包含go.mod文件 (2) 当前文件在包含go.mod文件的目录下面。

**注:**修改 GO111MODULE 参数可以用 go env -w GO111MODULE=on

3.3 如何在项目中使用 go.mod ?

1.新建项目,在GOPATH/src 目录之外

go.mod文件一旦创建后,它的内容将会被go toolchain全面掌控。go toolchain会在各类命令执行时,比如go get、go build、go mod等修改和维护go.mod文件。

go.mod 文件内提供了module, require、replace和exclude四个关键字

  • module语句指定包的名字(路径)
  • require语句指定的依赖项模块
  • replace语句可以替换依赖项模块
  • exclude语句可以忽略依赖项模块

2.在当前目录下,命令行运行 go mod init + 模块名称 来初始化模块

初始化之后,会在当前目录下生成一个go.mod文件,这是一个go用来管理包的关键文件

**注1:**为了确保一致性构建,Go引入了go.mod文件来标记每个依赖包的版本,在构建过程中go命令会下载go.mod中的依赖包,下载的依赖包会缓存在本地,以便下次构建。 考虑到下载的依赖包有可能是被黑客恶意篡改的,以及缓存在本地的依赖包也有被篡改的可能,单单一个go.mod文件并不能保证一致性构建。

为了解决Go module的这一安全隐患,Go开发团队在引入go.mod的同时也引入了go.sum文件,用于记录每个依赖包的哈希值,在构建时,如果本地的依赖包hash值与go.sum文件中记录得不一致,则会拒绝构建。

**注2:**go.sum 不需要手工维护,所以可以不用太关注。

**注3:**子目录里是不需要init的,所有的子目录里的依赖都会组织在根目录的go.mod文件里

**注4:**使用Go的包管理方式,依赖的第三方包被下载到了$GOPATH/pkg/mod路径下。

**注5:**版本是在go.mod中指定的。如果,在go.mod中没有指定,go命令会自动下载代码中的依赖的最新版本。如果,在go.mod用require语句指定包和版本 ,go命令会根据指定的路径和版本下载包,指定版本时可以用latest,这样它会自动下载指定包的最新版本;

注6: go mod init 模块名 生成的go.mod文件里的第一行会申明 module 模块名

作用:例如在项目下新建目录 utils,创建一个tools.go文件

在根目录下的hello.go文件就可以 import “hello/utils” 引用utils

package main
 
import (
	"hello/utils"
	"github.com/astaxie/beego"
)
 
func main() {
	utils.PrintText("Hi")
}

3.4 go.mod 命令

  • go mod download 下载模块到本地缓存,缓存路径是 $GOPATH/pkg/mod/cache
  • go mod edit 是提供了命令版编辑 go.mod 的功能,例如 go mod edit -fmt go.mod 会格式化go.mod
  • go mod graph 把模块之间的依赖图显示出来
  • go mod init 初始化模块(例如把原本dep管理的依赖关系转换过来)
  • go mod tidy 增加缺失的包,移除没用的包
  • go mod vendor 把依赖拷贝到 vendor/ 目录下
  • go mod verify 确认依赖关系
  • go mod why 解释为什么需要包和模块

附 : go 相关命令

  1. 指定module的根目录并生成go.mod文件

    go mod init example.com/hello
    
  2. 下载并添加依赖到go.mod文件中

    go build, go test
    
  3. 查看module下的所有依赖

    go list -m all
    
  4. 更新稳定版依赖

    go get rsc.io/sampler
    
  5. 清理无用的依赖

    go mod tidy
    
  6. 将依赖复制到项目路径的vendor文件夹中

    go mod vendor
    
  7. 忽略cache里的包,只使用vendor目录里的依赖进行编译

    go build -mod=vendor
    
  8. 校验依赖并查看是否有修改

    go mod verify
    

**注1:**go mod 命令在 GOPATH里默认是执行不了的,因为GO111MODULE的默认值是auto。默认在GOPATH 里默认是执行不了的,因为 GO111MODULE 的默认值是 auto。默认在GOPATH 里是不会执行, 如果一定要强制执行,就设置环境变量为 on。

**注2:**go mod init 在没有接module名字的时候是执行不了的,会报错 go: cannot determine module path for source directory。

三、初始化项目

(1) 新建项目目录及初始化

1、新建项目目录

首先,我们可以选择一个心仪的文件夹,在它下面新建一个项目目录,名字的话可以根据自己的喜好来选择,就如下图一样,我新建了一个名为 go_server的项目目录,此刻它的下面空空如也。

image.png

2、初始化项目

新建项目后我们要做的第一件事情就是初始化项目,新建go.mod 文件对项目中依赖进行管理,具体方法可以参考上面文档进行,我这里 执行了

go mod init myblog-server

生成了一个go.mod 文件

image.png

3、导入Gin框架

3.1 什么是Gin

Gin 是一个用 Go (Golang) 编写的 HTTP web 框架。 它是一个类似于 martini 但拥有更好性能的 API 框架, 优于 httprouter,速度提高了近 40 倍。(以上为官网描述)

3.2 使用前提

使用gin需要Go的版本号为1.6或更高

3.3 安装gin

go get -u github.com/gin-gonic/gin

执行完后正常来说你的文件夹里就会多出一个go.sum文件,它的作用在上面有所提及,不过一般情况下不太需要关注它,所以我们可以暂且略过

image.png

4、创建入口文件 main.go

4.1 在根目录下新建一个入口文件 main.go

并输入以下代码

package main

import (
  "fmt"
  "github.com/gin-gonic/gin"
)

func main() {
  S := gin.Default()
  S.GET("/", func(c *gin.Context) {
    c.JSON(200, gin.H{"msg": "服务启动成功"})
  })
  err := S.Run(":8080")
  if err != nil {
    fmt.Println("服务器启动失败!")
  }
}

image.png

4.2 在根目录下使用 go run main.go 启动服务

image.png

这时候我们在浏览器中访问localhost:8080 或者 127.0.0.1:8080 就可以看到

image.png