Go 语言入门很简单:技巧和窍门 (Tips and Tricks)

简介: 本节将随着时间的推移而增长,但主要目标是分享一些有经验的开发人员在一段时间内发现的技巧。希望这些技巧能让新用户更快地提高工作效率。

140 个字符提示


  • leave your object oriented brain at home. Embrace the interface. @mikegehard


别想着面向对象了,拥抱接口吧。


  • Learn to do things the Go way, don’t try to force your language idioms into Go. @DrNic


学习用 Go 语言的方式做事,不要试图把你的语言习性强加给 Go。


  • It’s better to over do it with using interfaces than use too few of them. @evanphx


接口使用宜多不宜少。


  • Embrace the language: simplicity, concurrency, and composition. @francesc


拥抱这门语言:简单、并发和组合。



阅读他们在 golang.org 网站上的所有精彩文档。



多多使用 gofmt


  • read a lot of source code. @DrNic


阅读大量的源码。


  • Learn and become familiar with tools and utilities, or create your own! They are as vital to your success as knowing the language. @coreyprak


学习并熟悉工具和实用程序,或创建自己的工具和实用程序!它们对您的成功与了解语言一样重要

额外导入包的方法

还有其他几种导入包的方法。我们将在以下示例中使用 fmt 包:


  • import format "fmt" : 创建 fmt 的别名. 然后在所有使用 fmt 包内容的地方使用 format. 而不是 fmt.format.Println("Hello,World")
  • import . "fmt" : 多了个点号 . ,这种方式允许直接访问包的内容,无需在其前面加上 fmt
  • import _ "fmt" - 如果未使用 fmt ,则抑制与 fmt 相关的编译器警告,如果有则执行初始化函数。 fmt 的其余部分无法访问。

goimports

Goimports 是一种更新 Go 导入行、添加缺失行和删除未引用行的工具。


它的作用与 gofmt(插入式替换)相同,但除了代码格式之外,还修复了导入。

代码组织

Go 是一种非常简单的编程语言,但首先是开发人员最难的事情是如何组织代码。由于许多原因,轨道变得流行,并且脚手架是其中之一。它给出了新的开发人员清晰的指示和地方,以便将其代码和成语遵循。


在某种程度上,Go 通过为开发人员提供很棒的工具(如 go fmt)以及不会编译未使用的变量或未使用的导入语句的严格编译器来做同样的事情。

自定义构造函数

我经常听到的一个问题是我应该什么时候使用像 NewJob 这样的自定义构造函数。我的答案是,在大多数情况下你不需要。但是,每当您需要在初始化时间设置值并且您有某种默认值时,它都是构造函数的好候选者。在上面的示例中,添加构造函数会产生很多意义,因此我们可以设置默认记录器。

package main
import (
    "log"
    "os"
)
type Job struct {
    Command string
    *log.Logger
}
func NewJob(command string) *Job {
    return &Job{command, log.New(os.Stderr, "Job: ", log.Ldate)}
}
func main() {
    NewJob("demo").Print("starting now...")
}


集合

您可能希望找到一种方法来从集合中提取唯一值。用其他语言,您通常具有不允许重复的集数据结构。Go 没有内置的,但它不太难以实现(由于缺乏泛型,你需要为大多数类型做到这一点,这可能是麻烦的)。

// UniqStr returns a copy if the passed slice with only unique string results.
func UniqStr(col []string) []string {
    m := map[string]struct{}{}
    for _, v := range col {
        if _, ok := m[v]; !ok {
            m[v] = struct{}{}
        }
    }
    list := make([]string, len(m))
    i := 0
    for v := range m {
        list[i] = v
        i++
    }
    return list
}


我使用了一些有趣的技巧。首先,空结构体的映射:

m := map[string]struct{}{}

我们创建了一个映射,键是我们想要唯一的值,关联的值并不重要,所以它可以是任何东西。例如:

m := map[string]bool{}


然而,我选择了一个空结构,因为它会像布尔值一样快,但不会分配那么多内存。


第二个技巧可以看得更清楚一点:

if _, ok := m[v]; !ok {
  m[v] = struct{}{}
}

我们在这里所做的,只是检查映射 m 中是否有与键 v 关联的值,我们不关心值本身,但是如果我们知道我们没有值,那么我们添加一个。


一旦我们有了一个带有唯一键的映射,我们就可以将它们提取到一个新的字符串切片中并返回结果。


下面是这个函数的测试,如你所见,我使用了一个表测试,这是运行单元测试的惯用 Go 方式:

func TestUniqStr(t *testing.T) {
    data := []struct{ in, out []string }{
        {[]string{}, []string{}},
        {[]string{"", "", ""}, []string{""}},
        {[]string{"a", "a"}, []string{"a"}},
        {[]string{"a", "b", "a"}, []string{"a", "b"}},
        {[]string{"a", "b", "a", "b"}, []string{"a", "b"}},
        {[]string{"a", "b", "b", "a", "b"}, []string{"a", "b"}},
        {[]string{"a", "a", "b", "b", "a", "b"}, []string{"a", "b"}},
        {[]string{"a", "b", "c", "a", "b", "c"}, []string{"a", "b", "c"}},
    }
    for _, exp := range data {
        res := UniqStr(exp.in)
        if !reflect.DeepEqual(res, exp.out) {
            t.Fatalf("%q didn't match %q\n", res, exp.out)
        }
    }
}

依赖包管理

不幸的是,Go 没有自带依赖包管理系统。可能是因为它起源于 C 文化,包没有版本化,也没有解决显式的版本依赖问题。


挑战是,如果您的项目上有多个开发人员,则希望所有这些都在依赖项的同一版本上。您的依赖项也可能有自己的依赖性,并且您希望确保一切顺利。当您使用不同版本的相同依赖项时,它会产生甚至欺骗者。这通常是 CI 环境中的情况。


在我们的 CI 环境中,我们在运行测试套件之前将 GOPATH 设置为项目特定的文件夹,因此项目之间不会共享包。

善用错误

错误是 Go 中非常重要的模式,起初,新开发人员对返回值和错误的函数数量感到惊讶。


Go 没有您可能在其他编程语言中看到的异常概念。 Go 确实有一种叫做 panic 的东西,但正如它的名字所暗示的那样,它们真的很特别,不应该被拯救(也就是说,它们可以)。


首先,Go 的错误处理似乎繁琐和重复,但迅速成为我们思考方式的一部分。而不是创建泡起来且可能或可能不会处理或通过更高的异常,而是错误是响应的一部分,并且旨在由呼叫者处理。每当函数可能会生成错误时,其响应应包含错误参数。

相关文章
|
16天前
|
Go
go语言中的数据类型
go语言中的数据类型
13 0
|
3天前
|
数据采集 存储 Go
使用Go语言和chromedp库下载Instagram图片:简易指南
Go语言爬虫示例使用chromedp库下载Instagram图片,关键步骤包括设置代理IP、创建带代理的浏览器上下文及执行任务,如导航至用户页面、截图并存储图片。代码中新增`analyzeAndStoreImage`函数对图片进行分析和分类后存储。注意Instagram的反爬策略可能需要代码适时调整。
使用Go语言和chromedp库下载Instagram图片:简易指南
|
21天前
|
存储 安全 Go
掌握Go语言:Go语言类型转换,无缝处理数据类型、接口和自定义类型的转换细节解析(29)
掌握Go语言:Go语言类型转换,无缝处理数据类型、接口和自定义类型的转换细节解析(29)
|
23小时前
|
Go
Golang深入浅出之-Go语言函数基础:定义、调用与多返回值
【4月更文挑战第21天】Go语言函数是代码组织的基本单元,用于封装可重用逻辑。本文介绍了函数定义(包括基本形式、命名、参数列表和多返回值)、调用以及匿名函数与闭包。在函数定义时,注意参数命名和注释,避免参数顺序混淆。在调用时,要检查并处理多返回值中的错误。理解闭包原理,小心处理外部变量引用,以提升代码质量和可维护性。通过实践和示例,能更好地掌握Go语言函数。
9 1
Golang深入浅出之-Go语言函数基础:定义、调用与多返回值
|
1天前
|
程序员 Go API
【Go语言快速上手(二)】 分支与循环&函数讲解
【Go语言快速上手(二)】 分支与循环&函数讲解
|
2天前
|
Go
Golang深入浅出之-Go语言基础语法:变量声明与赋值
【4月更文挑战第20天】本文介绍了Go语言中变量声明与赋值的基础知识,包括使用`var`关键字和简短声明`:=`的方式,以及多变量声明与赋值。强调了变量作用域、遮蔽、初始化与零值的重要性,并提醒读者注意类型推断时的一致性。了解这些概念有助于避免常见错误,提高编程技能和面试表现。
16 0
|
2天前
|
编译器 Go 开发者
Go语言入门|包、关键字和标识符
Go语言入门|包、关键字和标识符
20 0
|
5天前
|
API Go
使用Go语言通过API获取代理IP并使用获取到的代理IP
使用Go语言通过API获取代理IP并使用获取到的代理IP
|
7天前
|
前端开发 Java Go
开发语言详解(python、java、Go(Golong)。。。。)
开发语言详解(python、java、Go(Golong)。。。。)
|
16天前
|
存储 Java 编译器
go语言基础语法
go语言基础语法