使用系统粘贴板 利用 github.com/atotto/clipboard
模块, 如:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 package mainimport ( "fmt" "github.com/atotto/clipboard" )func main () { text := "Hello, World!" err := clipboard.WriteAll(text) if err != nil { fmt.Println("Error copying to clipboard:" , err) return } fmt.Println("Text copied to clipboard successfully!" ) }
` 和 “ 前者 (反引号) 用于包裹原始字面值, 后者 (双引号) 用于包裹解释字面值.
正则表达式捕获 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 package mainimport ( "fmt" "regexp" )func main () { re := regexp.MustCompile(`(\d{4})-(\d{2})-(\d{2})` ) str := "今天是2022-01-31,明天是2022-02-01。" match := re.FindStringSubmatch(str) if len (match) > 0 { fmt.Println("完整匹配:" , match[0 ]) fmt.Println("年份:" , match[1 ]) fmt.Println("月份:" , match[2 ]) fmt.Println("日期:" , match[3 ]) } else { fmt.Println("未找到匹配的日期" ) } }
查找字符串中子字符串的起始和结束索引 判断一个变量的类型 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 package mainimport ( "fmt" "reflect" )type Person struct { Name string Age int }func main () { p := Person{ Name: "John" , Age: 30 , } var v interface {} = p if isPerson(v) { fmt.Println("It's Person" ) } else { fmt.Println("It's not Person" ) } }func isPerson (v interface {}) bool { personType := reflect.TypeOf(Person{}) valueType := reflect.TypeOf(v) if valueType.Kind() == reflect.Ptr { valueType = valueType.Elem() } return valueType == personType }
判断一个成员是否被结构体定义 用 reflect
包中的 FieldByName
函数:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 package mainimport ( "fmt" "reflect" )type Person struct { Name string Age int Email string }func main () { p := Person{ Name: "John" , Age: 30 , } _, exists := reflect.TypeOf(p).FieldByName("hello" ) if exists { fmt.Println("hello is defined" ) } else { fmt.Println("hello does not define" ) } }
判断一个文件是否为可执行文件 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 package mainimport ( "fmt" "os" )func main () { filename := "example.exe" fileInfo, err := os.Stat(filename) if err != nil { fmt.Println("Error:" , err) return } mode := fileInfo.Mode() if mode.IsRegular() && mode.Perm()&0100 != 0 { fmt.Println("The file is executable." ) } else { fmt.Println("The file is not executable." ) } }
启动一个独立于源程序的进程 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 package mainimport ( "log" "os" "os/exec" "syscall" )func main () { cmd := exec.Command("/path/to/your/program" , "arg1" , "arg2" ) cmd.Stdout = os.Stdout cmd.Stderr = os.Stderr cmd.SysProcAttr = &syscall.SysProcAttr{ Setpgid: true , } err := cmd.Start() if err != nil { log.Fatalf("启动进程失败:%v" , err) } err = cmd.Wait() if err != nil { log.Printf("命令执行失败:%v" , err) } }
简短声明的注意事项 :=
运算符只能用于函数内部, 在函数外部声明需要用完整的 var
声明语法:
1 2 3 4 5 6 7 8 9 10 11 12 13 package mainimport "fmt" var Protocol = []string {} func main () { Protocol = append (Protocol, "HTTP" , "HTTPS" , "FTP" ) fmt.Println(Protocol) }
strings 包中的 Builder, Reader, Replacer 类型 type Builder 空结构体, 用于标记类型:
1 2 3 type Builder struct { }
该类型用于高效构建大型字符串, 提供有创建, 拼接字符串的方法.
示例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 package mainimport ( "fmt" "strings" )func main () { var builder strings.Builder builder.WriteString("Hello, " ) builder.WriteString("World!" ) result := builder.String() fmt.Println(result) }
type Reader 1 2 3 type Reader struct { }
该类型实现了 io.Reader
接口, 用于从字符串中读取数据.
示例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 package mainimport ( "fmt" "strings" )func main () { reader := strings.NewReader("Hello, World!" ) buffer := make ([]byte , 5 ) n, err := reader.Read(buffer) if err != nil { fmt.Println(err) return } fmt.Println(string (buffer[:n])) }
type Replacer 1 2 3 type Replacer struct { }
提供方便的字符串替换操作.
示例:
1 2 3 4 5 6 7 8 9 10 11 12 13 package mainimport ( "fmt" "strings" )func main () { replacer := strings.NewReplacer("Hello" , "Hi" , "World" , "Gopher" ) result := replacer.Replace("Hello, World!" ) fmt.Println(result) }
展开一个变量的所有内容 用 “github.com/davecgh/go-spew/spew” 包:
1 2 3 4 5 import "github.com/davecgh/go-spew/spew" spew.Dump(myVar1, myVar2, ...) spew.Fdump(someWriter, myVar1, myVar2, ...) str := spew.Sdump(myVar1, myVar2, ...)
语法展开切片语法 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 package mainimport "fmt" func printNames (names ...string ) { for _, name := range names { fmt.Println(name) } }func main () { nameSlice := []string {"Alice" , "Bob" , "Carol" } printNames(nameSlice...) printNames("David" , "Eve" , "Frank" ) }
这里函数接受的是不确定数量的 string
数量, 因此直接传入切片不行, 需要将切片展开.
对数组的不同索引做处理 利用 switch
语句:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 var t textinput.Modelfor i := range m.inputs { t = textinput.New() t.Cursor.Style = cursorStyle t.CharLimit = 32 switch i { case 0 : t.Placeholder = "Nickname" t.Focus() t.PromptStyle = focusedStyle t.TextStyle = focusedStyle case 1 : t.Placeholder = "Email" t.CharLimit = 64 case 2 : t.Placeholder = "Password" t.EchoMode = textinput.EchoPassword t.EchoCharacter = '•' } m.inputs[i] = t }
Go 语言字符串排序 利用 sort
包:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 package mainimport ( "fmt" "sort" )func main () { names := []string {"Alice" , "Bob" , "Eve" , "David" , "Carol" } sort.Strings(names) fmt.Println(names) }
输出为:
1 [Alice Bob Carol David Eve]
switch true switch
语句没有表达式, 是一种特殊形式的 switch 语句, 用于替代一系列的 if-else
语句. 其匹配执行第一个满足条件的 case
分支:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 package mainimport "fmt" func main () { day := 3 switch { case day == 1 : fmt.Println("day one" ) case day == 2 : fmt.Println("day two" ) case day == 3 : fmt.Println("day three" ) default : fmt.Println("other" ) } }
strconv 库的使用 用于类型转换, 如将数字转换为字符串:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 package mainimport ( "fmt" "strconv" )func main () { str := "Hello" num := 42 result := str + " " + strconv.Itoa(num) fmt.Println(result) result2 := fmt.Sprintf("%s %d" , str, num) fmt.Println(result2) }
用 iota 生成连续递增值 iota
名称来源于希腊字母表中的第九个字母, 表示第九个常量, 其在 Go 中用于在常量声明中生成连续递增值, 如:
1 2 3 4 5 const ( todo status = iota inProgress done )
os/exec
package 的用法用于运行外部命令, 不同于 C 语言的 system
调用, 其不调用系统 shell, 也无管道和通配符等.
示例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 package mainimport ( "bytes" "fmt" "os/exec" )func main () { cmd := exec.Command("grep" , "world" ) input := []byte ("Hello, world!\nGoodbye, world!" ) cmd.Stdin = bytes.NewBuffer(input) output, err := cmd.Output() if err != nil { fmt.Println("Fail to run " , err) return } fmt.Println(string (output)) }
cmd.Output()
会运行并返回值.
类型断言语法 用于在运行时, 判断一个 “接口类型” 的值的 “实际类型”, 如:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 package mainimport "fmt" func processMessage (msg interface {}) { switch msg := msg.(type ) { case string : fmt.Println("接收到字符串消息:" , msg) case int : fmt.Println("接收到整数消息:" , msg) default : fmt.Println("接收到未知类型的消息" ) } }func main () { processMessage("Hello" ) processMessage(42 ) processMessage(true ) }
(意思就是其返回值是 “类型”)
也可以转换为对应类型.
返回 error 类型的函数 引入 errors
包, 用 errors.New()
创建 error
类型的值, 示例:
1 2 3 4 import "errors" func Test () error { return errors.New("Test" ) }
获取当前时间并格式化输出 使用 time
标准库, 用 time.Now()
获取当前时间, 用 time.Format()
格式化, 示例:
1 2 3 4 5 6 7 8 9 10 11 12 package mainimport ( "fmt" "time" )func main () { currentTime := time.Now() formattedTime := currentTime.Format("20060102-15-04-05" ) fmt.Println(formattedTime) }
复制文件 用 io.Copy(dest, src)
, 示例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 package mainimport ( "fmt" "io" "os" )func main () { sourceFile := "source.txt" destinationFile := "destination.txt" err := copyFile(sourceFile, destinationFile) if err != nil { fmt.Println("Failed to copy file:" , err) return } fmt.Println("File copied successfully." ) }func copyFile (sourceFile, destinationFile string ) error { src, err := os.Open(sourceFile) if err != nil { return err } defer src.Close() dest, err := os.Create(destinationFile) if err != nil { return err } defer dest.Close() _, err = io.Copy(dest, src) if err != nil { return err } return nil }
判断文件/目录是否存在 用 os.Stat()
, 其返回一个 os.FileInfo
类型的对象, 包含文件/目录的信息. 示例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 package mainimport ( "fmt" "os" )func main () { dirname := "mydir" _, err := os.Stat(dirname) if os.IsNotExist(err) { fmt.Println("Directory does not exist." ) } else if err != nil { fmt.Println("Failed to get directory information:" , err) } else { fmt.Println("Directory exists." ) } }
创建目录 用 os.Mkdir()
或 os.MkdirAll()
(后者会递归创建), 示例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 package mainimport ( "fmt" "os" )func main () { err := os.Mkdir("mydir" , 0755 ) if err != nil { fmt.Println("Failed to create directory:" , err) return } fmt.Println("Directory created successfully." ) err = os.MkdirAll("mydir/nested/subdirectory" , 0755 ) if err != nil { fmt.Println("Failed to create nested directory:" , err) return } fmt.Println("Nested directory created successfully." ) }
删除文件 用 os.Remove()
, 示例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 package mainimport ( "fmt" "os" )func main () { err := os.Remove("example.txt" ) if err != nil { fmt.Println("Failed to delete file:" , err) return } fmt.Println("File deleted successfully." ) }
创建文件并写入文本 用 os.Create()
创建文件. 用 handle.WriteString()
写入, 示例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 package mainimport ( "fmt" "os" )func main () { file, err := os.Create("example.txt" ) if err != nil { fmt.Println("Failed to create file:" , err) return } defer file.Close() content := "This is the content that will be written to the file." _, err = file.WriteString(content) if err != nil { fmt.Println("Failed to write to file:" , err) return } fmt.Println("File created and written successfully." ) }
正则替换 用 regexp
中的 ReplaceAllString()
或 ReplaceAllStringFunc()
, 示例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 package mainimport ( "fmt" "regexp" )func main () { str := "Hello, World!" re := regexp.MustCompile(`World` ) result := re.ReplaceAllString(str, "Gopher" ) fmt.Println(result) }`` ` # 正则匹配 使用标准库中的 ` regexp`, 需要先编译正则表达式, 然后再使用. 编译用 ` regexp.Compile()` 或 ` regexp.MustCompile()`, 后者在编译失败时会引发 panic. ` `` go pattern := regexp.MustCompile(`\d+` )
匹配用 pattern.MatchString(str)
或 FindString()
, FindAllString()
:
1 matchedString := pattern.FindString(str)
示例如:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 package mainimport ( "fmt" "regexp" )func main () { str := "Hello, 123 World!" pattern := regexp.MustCompile(`\d+` ) matched := pattern.MatchString(str) fmt.Println("Matched:" , matched) matchedString := pattern.FindString(str) fmt.Println("Matched String:" , matchedString) }
忽略变量中的特殊字符 用 regexp.QuoteMeta()
进行转义, 如:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 package mainimport ( "fmt" "regexp" )func main () { str := "Hello (World)!" pattern := regexp.QuoteMeta("Hello (World)!" ) reg := regexp.MustCompile(pattern) matched := reg.MatchString(str) fmt.Println("Matched:" , matched) }
遍历目录 用 filepath.Walk()
函数, 其函数签名为:
1 func Walk (root string , walkFn WalkFunc) error
root
指要遍历的目录.
WalkFunc
会对每个访问到的文件/目录做处理, 其定义需为:
1 type WalkFunc func (path string , info os.FileInfo, err error ) error
path
, 为文件/目录的绝对路径
info
, 提供文件元信息, 常见的有 Name()
, Size()
, Mode()
, ModTime()
, IsDir()
, Sys()
err
, 包含错误信息
示例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 `` ` # 结构体的标签 注意: 在标签中, 冒号 ":" 后面应该没有空格 如: ` `` go type Main struct { Sort string `yaml:"sort"` Help struct { Hidden bool `yaml:"hidden"` } `yaml:"help"` } `yaml:"main"`
文件路径拼接 用 path/filepath
标准包.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 package mainimport ( "fmt" "path/filepath" )func main () { dir := "/path/to/dir" filename := "file.txt" absolutePath := filepath.Join(dir, filename) fmt.Println("Absolute Path:" , absolutePath) }
log 标准包 log.Fatal()
会默认将错误输出到 stderr
, 然后调用 os.Exit(1)
终止程序.
安装包 如:
1 go get -u github.com/charmbracelet/glamour
.(type)
一种特殊语法, 只能用于 switch
或者 select
语句中, 其可以先获取接口的实际类型, 在选择了一个分支后, 将变量的接口类型转换为对应的实际类型:
1 2 3 4 5 6 7 8 switch msg := msg.(type ) {case string : fmt.Println("这是一个字符串:" , msg)case int : fmt.Println("这是一个整数:" , msg)default : fmt.Println("未知类型" ) }
读取/写入文件
读取
1 data, err := os.ReadFile("filename" )
写入
1 err = os.WriteFile("filename" , data, 0644 )
(0644
中的 “0” 表示其为 8 进制数, “644” 为权限)