golang 包推荐
大约 5 分钟
官方仓库:https://pkg.go.dev
示例源码仓库:https://gitee.com/orangbus/study-go
m3u8 解析库
go get -u github.com/grafov/m3u8
定时器
https://github.com/robfig/cron
go get -u github.com/robfig/cron/v3
func main() {
c := cron.New()
ch := make(chan int)
go func() {
c.AddFunc("@daily", func() {
time.Sleep(time.Second * 2)
fmt.Printf("%s\n", dns)
ch <- 1
})
}()
c.Start()
for {
data := <-ch
fmt.Println(data)
}
}
gin
go get -u github.com/gin-gonic/gin
goquery
go get -u github.com/PuerkitoBio/goquery
获取某个节点
func TestNode(t *testing.T) {
url := "https://www.hf960.com/n5061c23.aspx"
response, err := http.Get(url)
if err != nil {
panic(err)
}
defer response.Body.Close()
doc, err := goquery.NewDocumentFromReader(response.Body)
if err != nil {
panic(err)
}
selection := doc.Selection.Find("#bodyTd")
fmt.Println(selection.Find(".aTitle").Text())
fmt.Println(selection.Find("#content").Html())
}
获取列表
viper
https://github.com/spf13/viper
go get github.com/spf13/viper
go get github.com/spf13/cast // 类型转化
APP_NAME=orangbus
APP_KEY=zBqYyQrPNaIUsnRhsGtHLivjqiMjBVLS
APP_DEBUG=true
APP_URL=http://localhost:3000
APP_PORT=3000
/pkg/config/config.go
package config
import (
"github.com/spf13/cast"
viperlib "github.com/spf13/viper"
"orangbus.cn/study-go/index/pkg/helpers"
)
// Initialize 触发加载 config 包的所有 init 函数
func Initialize() {
}
var viper *viperlib.Viper
// ConfigFunc 动态加载配置信息
type ConfigFun func() map[string]interface{}
// ConfigFuncs 先加载到此数据, loadConfig 在动态生成配置信息
var ConfigFuncs map[string]ConfigFun
var configPath = ".env" // main.go 同目录下的 .env 文件
func init() {
viper = viperlib.New()
viper.SetConfigType("env")
viper.AddConfigPath(".")
viper.SetEnvPrefix("appenv")
// 读取环境变量
viper.AutomaticEnv()
ConfigFuncs = make(map[string]ConfigFun)
}
func InitConfig() {
// 加载环境变量
loadEnv()
// 注册配置信息
loadConfig()
}
func loadConfig() {
for name, fn := range ConfigFuncs {
viper.Set(name, fn())
}
}
func loadEnv() {
viper.SetConfigName(configPath)
if err := viper.ReadInConfig(); err != nil {
panic(err)
}
// 变更时重新加载
viper.WatchConfig()
}
func internalGet(path string, defaultValue ...interface{}) interface{} {
if !viper.IsSet(path) || helpers.Empty(viper.Get(path)) {
if len(defaultValue) > 0 {
return defaultValue[0]
}
return nil
}
return viper.Get(path)
}
// 读取环境变量,支持默认值
func Env(envName string, defaultValue ...interface{}) interface{} {
if len(defaultValue) > 0 {
return internalGet(envName, defaultValue[0])
}
return internalGet(envName)
}
func Add(name string, configFun ConfigFun) {
ConfigFuncs[name] = configFun
}
// GetString 获取 String 类型的配置信息
func GetString(path string, defaultValue ...interface{}) string {
return cast.ToString(internalGet(path, defaultValue...))
}
// GetInt 获取 Int 类型的配置信息
func GetInt(path string, defaultValue ...interface{}) int {
return cast.ToInt(internalGet(path, defaultValue...))
}
// GetBool 获取 Bool 类型的配置信息
func GetBool(path string, defaultValue ...interface{}) bool {
return cast.ToBool(internalGet(path, defaultValue...))
}
// GetStringMapString 获取结构数据
func GetStringMapString(path string) map[string]string {
return viper.GetStringMapString(path)
}
/pkg/helpers/helpers.go
// Package helpers 存放辅助方法
package helpers
import "reflect"
// Empty 类似于 PHP 的 empty() 函数
func Empty(val interface{}) bool {
if val == nil {
return true
}
v := reflect.ValueOf(val)
switch v.Kind() {
case reflect.String, reflect.Array:
return v.Len() == 0
case reflect.Map, reflect.Slice:
return v.Len() == 0 || v.IsNil()
case reflect.Bool:
return !v.Bool()
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
return v.Int() == 0
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
return v.Uint() == 0
case reflect.Float32, reflect.Float64:
return v.Float() == 0
case reflect.Interface, reflect.Ptr:
return v.IsNil()
}
return reflect.DeepEqual(val, reflect.Zero(v.Type()).Interface())
}
/config/app.go
package config
import "orangbus.cn/study-go/index/pkg/config"
func init() {
config.Add("app", func() map[string]interface{} {
return map[string]interface{}{
"name": config.Env("APP_NAME", "orangbus"),
"key": config.Env("APP_KEY", "33446a9dcf9ea060a0a6532b166da32f304af0de"),
"debug": config.Env("APP_DEBUG", false),
"port": config.Env("APP_PORT", 3000),
"url": config.Env("APP_URL", "http://localhost"),
}
})
}
main.go
package main
import (
"fmt"
"orangbus.cn/study-go/index/pkg/config"
)
func init() {
config.Initialize()
config.InitConfig()
}
func main() {
fmt.Println(config.GetInt("app_port"))
fmt.Println(config.GetInt("APP_PORT"))
}
示例2
gorm
https://gorm.io/zh_CN/docs/index.html
go get gorm.io/gorm
go get gorm.io/driver/sqlite
go get gorm.io/driver/mysql
1、初始化
bootstrap/database.go
package bootstrap
import (
"database-gorm/pkg/database"
"gorm.io/driver/sqlite"
"gorm.io/gorm"
"os"
"path/filepath"
)
func SetupDatabase() {
var dbConfig gorm.Dialector
dbConfig = sqlite.Open(getDatabasePath())
database.Connect(dbConfig)
}
func getDatabasePath() string {
basePath, err := os.Getwd()
if err != nil {
return "database/database.sqlite"
}
return filepath.Join(basePath, "database/database.sqlite")
}
2、连接数据库
/pkg/database/database.go
package database
import (
"database/sql"
"gorm.io/gorm"
"time"
)
var (
DB *gorm.DB
SqlDB *sql.DB
)
/*
*
连接数据库
*/
func Connect(dbConfig gorm.Dialector) {
var err error
DB, err = gorm.Open(dbConfig, &gorm.Config{
CreateBatchSize: 500,
})
if err != nil {
panic(err)
}
SqlDB, err = DB.DB()
SqlDB.SetMaxIdleConns(10)
SqlDB.SetMaxOpenConns(10)
SqlDB.SetConnMaxLifetime(time.Hour)
if err != nil {
panic(err)
}
}
faker
https://pkg.go.dev/github.com/bxcodec/faker/v3
go get -u github.com/bxcodec/faker/v3
package factories
import (
"database-gorm/app/models"
"database-gorm/pkg/database"
"github.com/bxcodec/faker/v3"
)
func FakerUser(number int) {
userList := []models.User{}
for i := 0; i < number; i++ {
user := models.User{
Name: faker.Name(),
Phone: faker.Phonenumber(),
Password: faker.Password(),
}
userList = append(userList, user)
}
// 插入到数据库中
database.DB.CreateInBatches(userList, 500)
}
uuid
go get -u github.com/google/uuid
package test
import (
"fmt"
"github.com/google/uuid"
"testing"
)
func TestUUid(t *testing.T) {
fmt.Println(uuid.NewString()) // 6749b706-bb35-4760-9a23-f3ef65101e6c
}
cron
go get -u github.com/robfig/cron/v3
bcrypt 加密
go get golang.org/x/crypto/bcrypt
package test
import (
"fmt"
"golang.org/x/crypto/bcrypt"
"testing"
)
var password = "admin666"
// 加密
func TestBcrypt(t *testing.T) {
passwd, err := bcrypt.GenerateFromPassword([]byte(password), bcrypt.DefaultCost)
if err != nil {
fmt.Println(passwd)
return
}
fmt.Println(string(passwd)) // $2a$10$zVPrJ.kiAWKqEKhuYjSpAu9QAjj/Mp7Mnn5P5dRRO8IvMqMkEzXR.
}
// 密码比对
func TestComparePwd(t *testing.T) {
hashPasswd := "$2a$10$zVPrJ.kiAWKqEKhuYjSpAu9QAjj/Mp7Mnn5P5dRRO8IvMqMkEzXR."
err := bcrypt.CompareHashAndPassword([]byte(hashPasswd), []byte(password))
if err != nil {
fmt.Println(err)
return
}
fmt.Println("密码相同")
}
jwt
https://github.com/dgrijalva/jwt-go
go get github.com/dgrijalva/jwt-go
pkg/jwtToken/jwtToken
package jwtToken
import (
"gin-web/app/models"
"github.com/dgrijalva/jwt-go"
"time"
)
const app_key = "orangbus.cn"
const expire_at = 30 // 失效天数
type jwtClaims struct {
ID uint64 `json:"id"`
Name string `json:"name"`
jwt.StandardClaims
}
func GenerateToken(user models.User) (string, error) {
claims := jwt.NewWithClaims(jwt.SigningMethodHS256, jwt.MapClaims{
"id": user.ID,
"name": user.Name,
"phone": user.Phone,
"exp": time.Now().Add(time.Hour * 24 * expire_at).Unix(),
"iat": time.Now().Unix(), // 发布时间
})
token, err := claims.SignedString([]byte(app_key))
if err != nil {
return "", err
}
return token, nil
}
func Parse(token string) (models.User, error) {
user := models.User{}
parse, err := jwt.Parse(token, func(token *jwt.Token) (interface{}, error) {
return []byte(app_key), nil
})
if err != nil {
return models.User{}, err
}
if claims, ok := parse.Claims.(jwt.MapClaims); ok && parse.Valid {
user.ID = int64(uint64(claims["id"].(float64)))
user.Name = claims["name"].(string)
user.Phone = claims["phone"].(string)
}
return user, nil
}
func ValidateToken(token string) (bool, error) {
return true, nil
}
webscoket
go-redis
go get github.com/redis/go-redis/v9
pkg/cache/redis
package cache
import (
"context"
"github.com/redis/go-redis/v9"
"movie-cloud/pkg/config"
"runtime"
"time"
)
var (
Redis *redis.Client
prefix = "movie_cloud_"
ctx = context.Background()
)
/*
*
连接数据库
*/
func ConnectRedis() {
Redis = redis.NewClient(&redis.Options{
Addr: config.GetRedisHost(),
Password: config.GetRedisPassword(),
DB: config.GetRedisDB(),
PoolSize: runtime.GOMAXPROCS(100),
// 最小空闲连接数,受PoolSize限制
MinIdleConns: 10,
})
}
func Put(key, value string, duration ...int) {
t := time.Duration(0)
if len(duration) == 0 {
t = time.Duration(duration[0])
}
Redis.Set(ctx, prefix+key, value, t)
}
func Get(key string) (string, error) {
return Redis.Get(ctx, prefix+key).Result()
}
ip2region
https://github.com/lionsoul2014/ip2region?tab=readme-ov-file
https://github.com/lionsoul2014/ip2region/tree/master/binding/golang
package service
import (
"github.com/lionsoul2014/ip2region/binding/golang/xdb"
"strings"
)
var dbPath = "ip2region.xdb"
func GetIpInfo(ip string) (map[string]string, error) {
searcher, err := xdb.NewWithFileOnly(dbPath)
return nil, err
defer searcher.Close()
ipInfo, err := searcher.SearchByStr(ip)
return nil, err
info := strings.Split(ipInfo, "|")
region := map[string]string{}
region["ip"] = ip
region["county"] = info[0]
region["area"] = info[1]
region["region"] = info[2]
region["city"] = info[3]
region["isp"] = info[4]
return region, nil
}
markdown 解析
https://github.com/russross/blackfriday/v2
func GetReadme() (string, error) {
file, err := os.Open(readmePath)
if err != nil {
return "", err
}
defer file.Close()
bytes, err := io.ReadAll(file)
if err != nil {
return "", err
}
content := blackfriday.Run(bytes)
return string(content), nil
}
mapstructure
结构体绑定
go get github.com/mitchellh/mapstructure
air
go install github.com/cosmtrek/air@latest
air -v
webscoket
go get -u github.com/gorilla/websocket
前端连接
https://www.npmjs.com/package/vue3-websocket
npm i vue3-websocket
main.js
import { createApp } from 'vue'
import App from './App.vue'
import socket from 'vue3-websocket'
const app = createApp(App)
// app.use(socket, 'ws://localhost:9000')
app.use(socket, {
secured: false,
host: 'localhost:9000/ws',
protocols: ['soap']
})
app.mount('#app')
vue-templet
<template>
<input v-model="text" />
<button @click="sendMessage">Send a message</button>
</template>
<script setup>
import { ref, inject } from 'vue'
import { onMessage, onOpen, onClose, onError } from 'vue3-websocket'
const text = ref('')
const socket = inject('socket')
const sendMessage = () => socket.value.send(text.value)
//
onOpen(() => {
console.log('WS connection is stable! ~uWu~')
})
onMessage(message => {
console.log('Got a message from the WS: ', message)
})
onClose(() => {
console.log('No way, connection has been closed 😥')
})
onError(error => {
console.error('Error: ', error)
})
</script>
MongoDB
go get -u go.mongodb.org/mongo-driver
发送邮箱
excel 转化
pdf转化
调用系统命令
package main
import (
"fmt"
"os"
"os/exec"
)
func main() {
cmd := exec.Command("ls", "-l")
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr
err := cmd.Run()
if err != nil {
fmt.Println(err)
return
}
}