go mod
go env -w GOPROXY=https://goproxy.io
交叉编译
待更新
接口使用扫盲
Go 语言提供了另外一种数据类型即接口,它把所有的具有共性的方法定义在一起,任何其他类型只要实现了这些方法就是实现了这个接口。
log/logInterface.go
package log
type LogInterface interface {
LogDebug(message string)
LogWarn(message string)
LogError(message string)
}
file.go
package log
import "fmt"
type FileLog struct {}
func NewFileLog() LogInterface {
return &FileLog{}
}
func (f *FileLog) LogDebug(message string) {
fmt.Printf("file %s\n", message)
}
func (f *FileLog) LogWarn(message string) {
fmt.Printf("file %s\n", message)
}
func (f *FileLog) LogError(message string) {
fmt.Printf("file %s\n", message)
}
console.go
package log
import "fmt"
type ConsoleLog struct {}
func NewConsoleLog() LogInterface {
return &ConsoleLog{}
}
func (c *ConsoleLog) LogDebug(message string) {
fmt.Printf("console %s\n", message)
}
func (c *ConsoleLog) LogWarn(message string) {
fmt.Printf("console %s\n", message)
}
func (c *ConsoleLog) LogError(message string) {
fmt.Printf("console %s\n", message)
}
main.go
package main
import "test/log"
func main() {
mylog := log.NewFileLog()
mylog.LogDebug("this is a debug log...")
mylog.LogWarn("this is a warning log...")
mylog.LogError("this is a error log...")
mylog2 := log.NewConsoleLog()
mylog2.LogDebug("this is a debug log...")
mylog2.LogWarn("this is a warning log...")
mylog2.LogError("this is a error log...")
}
读写文件
读文件第一种方法
package main
import (
"fmt"
"io/ioutil"
"log"
"os"
)
func main() {
f, err := os.Open("test.go")
if err != nil {
log.Fatal(err)
}
defer f.Close()
data, err := ioutil.ReadAll(f)
if err != nil {
log.Fatal(err)
}
fmt.Printf("%s\n", data)
}
第二种方法(一次读取所有内容)
package main
import (
"fmt"
"io/ioutil"
"log"
)
func main() {
data, err := ioutil.ReadFile("test.go")
if err != nil {
log.Fatal(err)
}
fmt.Printf("%s\n", data)
}
逐行读取文件
package main
import (
"bufio"
"fmt"
"io"
"log"
"os"
)
func main() {
f, err := os.Open("test.go")
if err != nil {
log.Fatal(err)
}
defer f.Close()
reader := bufio.NewReader(f)
for {
line, _, err := reader.ReadLine()
if err == io.EOF {
break
}
fmt.Printf("%s\n", line)
}
}
写文件
文件打开方式
//打开方式
const (
//只读模式
O_RDONLY int = syscall.O_RDONLY // open the file read-only.
//只写模式
O_WRONLY int = syscall.O_WRONLY // open the file write-only.
//可读可写
O_RDWR int = syscall.O_RDWR // open the file read-write.
//追加内容
O_APPEND int = syscall.O_APPEND // append data to the file when writing.
//创建文件,如果文件不存在
O_CREATE int = syscall.O_CREAT // create a new file if none exists.
//与创建文件一同使用,文件必须存在
O_EXCL int = syscall.O_EXCL // used with O_CREATE, file must not exist
//打开一个同步的文件流
O_SYNC int = syscall.O_SYNC // open for synchronous I/O.
//如果可能,打开时缩短文件
O_TRUNC int = syscall.O_TRUNC // if possible, truncate file when opened.
)
打开模式
//打开模式
const (
ModeDir FileMode = 1 << (32 - 1 - iota) // d: is a directory 文件夹模式
ModeAppend // a: append-only 追加模式
ModeExclusive // l: exclusive use 单独使用
ModeTemporary // T: temporary file (not backed up) 临时文件
ModeSymlink // L: symbolic link 象征性的关联
ModeDevice // D: device file 设备文件
ModeNamedPipe // p: named pipe (FIFO) 命名管道
ModeSocket // S: Unix domain socket Unix 主机 socket
ModeSetuid // u: setuid 设置uid
ModeSetgid // g: setgid 设置gid
ModeCharDevice // c: Unix character device, when ModeDevice is set Unix 字符设备,当设备模式是设置Unix
ModeSticky // t: sticky 粘性的
// Mask for the type bits. For regular files, none will be set. bit位遮盖.不变的文件设置为none
ModeType = ModeDir | ModeSymlink | ModeNamedPipe | ModeSocket | ModeDevice
ModePerm FileMode = 0777 // Unix permission bits 权限位.
)
简单些文件第一种方式
package main
import (
"io/ioutil"
"log"
)
func main() {
err := ioutil.WriteFile("demo2.txt",[]byte("hello golang"), 0666)
if err != nil {
log.Fatal(err)
}
}
简单写文件第二种方式
package main
import (
"fmt"
"io"
"log"
"os"
)
func main() {
file, err := os.OpenFile("demo.txt", os.O_CREATE, 0666)
if err != nil {
log.Fatal(err)
}
defer file.Close()
n, err := io.WriteString(file, "hello world")
if err != nil {
log.Fatal(err)
}
fmt.Printf("写了%d个字节\n", n)
}
日志 log
错误 errors
待更新
序列化&反序列化
json
yaml
xml
反射 reflect
获取变量的类型
package main
import (
"fmt"
"reflect"
)
func main() {
var a int64 = 21
demo(a)
var b float32 = 3.85
demo(b)
var c int32
demo(c)
}
func demo(x interface{}) {
t := reflect.TypeOf(x)
fmt.Println(t.Kind())
switch t.Kind() {
case reflect.Int32:
fmt.Println("type is int32")
case reflect.Int64:
fmt.Println("type is int64")
case reflect.Float32:
fmt.Println("type is float32")
case reflect.Float64:
fmt.Println("type is float64")
default:
fmt.Println("is other type")
}
}
获取变量的值并修改
package main
import (
"fmt"
"reflect"
)
func main() {
var a int64 = 21
demo(&a)
fmt.Println("a=", a)
}
func demo(x interface{}) {
v := reflect.ValueOf(x)
fmt.Println(v.Kind())
switch v.Kind() {
case reflect.Int32:
fmt.Println("value is int32", v.Int())
case reflect.Int64:
v.SetInt(28)
fmt.Println("value is int64", v.Int())
case reflect.Float32:
fmt.Println("value is float32", v.Float())
case reflect.Float64:
fmt.Println("values is float64", v.Float())
case reflect.Ptr:
v.Elem().SetInt(999)
default:
fmt.Println("is other type value")
}
}
结构体反射
获取结构体类型
package main
import (
"fmt"
"reflect"
)
type Server struct {
Host string
Port int
Username string
Password string
}
func main() {
var s Server
s.Host = "127.0.0.1"
s.Port = 3306
s.Username = "root"
s.Password = "111111"
v := reflect.ValueOf(s)
fmt.Println(v.NumField())
for i:=0;i<v.NumField();i++{
f := v.Field(i)
fmt.Println(f.Type(), f.Type().Name(), f.Interface())
}
}
设置结构体的值
package main
import (
"fmt"
"reflect"
)
type Server struct {
Host string
Port int
Username string
Password string
}
func main() {
var s Server
s.Host = "127.0.0.1"
s.Port = 3306
s.Username = "root"
s.Password = "111111"
v := reflect.ValueOf(&s)
v.Elem().Field(0).SetString("192.168.1.1")
v.Elem().Field(1).SetInt(9980)
v.Elem().FieldByName("Username").SetString("admin")
v.Elem().FieldByName("Password").SetString("888888")
fmt.Println(s)
}
获取结构体的方法
package main
import (
"fmt"
"reflect"
)
type Persion struct {
Name string
Age int
}
func (s *Persion) Eat() {
fmt.Println(s.Name, "eat...")
}
func (s *Persion) Sleep() {
fmt.Println(s.Name, "sleep...")
}
func main() {
var p Persion
// 如果方法的接收者是指针类型,那么传参数要传变量的指针才可以
v := reflect.ValueOf(&p)
t := v.Type()
fmt.Println("method count:", v.NumMethod())
for i:=0; i<v.NumMethod(); i++{
method := t.Method(i)
fmt.Println(method.Type, method.Name, method.Func, method.Index, method.PkgPath)
}
}
调用结构体的方法
package main
import (
"fmt"
"reflect"
)
type Persion struct {
Name string
Age int
}
func (s *Persion) Eat() {
fmt.Println(s.Name, "eat...")
}
func (s *Persion) Sleep() {
fmt.Println(s.Name, "sleep...")
}
func (s *Persion) Test(name string, age int) {
fmt.Printf("name is %s, age is %d\n", name, age)
}
func main() {
var p Persion
// 如果方法的接收者是指针类型,那么传参数要传变量的指针才可以
v := reflect.ValueOf(&p)
var value []reflect.Value
value = append(value, reflect.ValueOf("王哈哈"))
value = append(value, reflect.ValueOf(25))
v.MethodByName("Test").Call(value)
}
获取结构体的Tag信息
指针传递
package main
import (
"fmt"
"reflect"
)
type Server struct {
Host string `json:"host" data:"host"`
Port int `json:"port" data:"port"`
}
func main() {
var s Server
v := reflect.ValueOf(&s)
t := v.Type()
for i:=0;i<t.Elem().NumField();i++ {
json := t.Elem().Field(i).Tag.Get("json")
data := t.Elem().Field(i).Tag.Get("data")
fmt.Printf("json: %v, data:%v\n", json, data)
}
}
or
值传递
package main
import (
"fmt"
"reflect"
)
type Server struct {
Host string `json:"host" data:"host"`
Port int `json:"port" data:"port"`
}
func main() {
var s Server
v := reflect.ValueOf(s)
t := v.Type()
for i:=0;i<t.NumField();i++ {
json := t.Field(i).Tag.Get("json")
data := t.Field(i).Tag.Get("data")
fmt.Printf("json: %v, data:%v\n", json, data)
}
}
总结
通过反射我们可以拿到变量和结构体的类型信息和值信息,可以动态修改变量的值和结构体的值,对于结构体而言可以调用结构体的方法,还可以获取结构体的Tag信息。
反射应用场景
通过反射我们可以使用在文件解析,ORM映射,反序列化等功能中。
信号
待更新
网络通信
待更新
数据库操作
mysql
redis
mongodb
go-jwt
结构体版
package main
import (
"fmt"
"github.com/dgrijalva/jwt-go"
"log"
"time"
)
type MyClaims struct {
Username string `json:"username"`
jwt.StandardClaims
}
func main() {
m := MyClaims{
"wanghaha",
jwt.StandardClaims{
NotBefore: time.Now().Unix(),
ExpiresAt: time.Now().Unix() + 60*60*3, // 3小时后过期
Issuer: "wanghaha",
},
}
mySigningKey := []byte("AllYourBase")
t := jwt.NewWithClaims(jwt.SigningMethodHS256, m)
tokenString, err := t.SignedString(mySigningKey)
if err != nil {
log.Fatal(err)
}
fmt.Println(tokenString)
// parse
token, err := jwt.ParseWithClaims(tokenString, &MyClaims{}, func(token *jwt.Token) (interface{}, error) {
return mySigningKey, nil
})
if err != nil {
fmt.Println(jwt.ValidationErrorExpired)
fmt.Println(err.Error())
log.Fatal(err)
}
// 这里去解析就好了
fmt.Println(token.Claims)
fmt.Println(token.Claims.(*MyClaims).Username)
}
map版
package main
import (
"fmt"
"github.com/dgrijalva/jwt-go"
"log"
"time"
)
func main() {
mySigningKey := []byte("AllYourBase")
t := jwt.NewWithClaims(jwt.SigningMethodHS256, jwt.MapClaims{
"exp": time.Now().Unix() + 60*60*3,
"iss": "wanghaha",
"nbf": time.Now(),
})
tokenString, err := t.SignedString(mySigningKey)
if err != nil {
log.Fatal(err)
}
fmt.Println(tokenString)
// parse
token, err := jwt.ParseWithClaims(tokenString, jwt.MapClaims{}, func(token *jwt.Token) (interface{}, error) {
return mySigningKey, nil
})
if err != nil {
fmt.Println(jwt.ValidationErrorExpired)
fmt.Println(err.Error())
log.Fatal(err)
}
// 这里去解析就好了
fmt.Println(token)
fmt.Println(token.Claims.(jwt.MapClaims)["exp"])
fmt.Println(token.Claims.(jwt.MapClaims)["iss"])
}