## 简介 在 Go 语言中,如果一个函数或者方法需要返回任何错误,通常会使用 error 接口类型作为返回类型。在标准库中,所有返回了错误信息的函数和方法使用的都是这个接口。例如,下面是 http 包中 Get 方法的声明: 清单 1.1 http://golang.org/pkg/net/http/#Client.Get ```go func (c *Client) Get(url string) (resp *Response, err error) ``` ...
-
Go 语言中的错误处理 - 第一部分
-
GO 中的调度:第三部分 - 并发
## 前奏 这篇文章是三部曲系列文章中的第三篇,这个系列的文章将会对 Go 中调度器背后的机制和语义做深入的了解。本文主要关注并发的部分。 Go 调度器系列文章: - [Go 中的调度器:第一部分 - 操作系统调度器](https://studygolang.com/articles/14264) - [Go 中的调度器:第二部分 - Go 调度器](https://studygolang.com/articles/15316) - [Go 中的调度器:第三部分 - 并发]...
-
Go Mock 测试
( 在开发的过程中 ) 你应该一直都写测试。不管使用什么语言,为了完全的理解如何能写出生产环境级别的应用,你应该拥有写单元测试的能力。有些人把测试驱动 (TDD) 做到极致。TDD 提倡你在写功能之前写测试。当你尝试写一些容易测试的代码的时候,这是个好方法。直到现在,我发现 TDD 很像 agile ( 敏捷软件开发 ); 很多人说他们有做测试驱动,但是实际中,他们只在一些混合的版本中做。到最后,它归根到底像,在吃牛排之前吃蔬菜的问题。( 西餐中 ) 比较健康的吃法是先吃蔬菜,然后吃牛排。就像在...
-
用 Testify 来改善 GO 测试和模拟
## 目录 - [入门指南](# 入门指南 ) - [一个简单的示例](# 一个简单的示例 ) - [否定测试案例和 Nil 测试](# 否定测试案例和 -Nil- 测试 ) - [将 Testify 与表驱动测试相结合](# 将 -Testify- 与表驱动测试相结合 ) - [模拟](# 模拟 ) - [模拟示例](# 模拟示例 ) - [用 Mockery 生成模仿对象](# 用 -Mockery- 生成模仿对象 ) - [关键点](# 关键点 ) - [...
-
Go 测试介绍
测试在所有软件中都非常重要,它能够确保代码的正确性,并确保你所做的任何更改,最终都不会破坏代码库中其他不同部分的任何内容,这一点非常重要。 通过花费时间来充分测试你的程序,可以让你自己开发得更快,并且有信心使你正在开发的项目发布到生产环境时,还可以持续的工作。 ## 视频教程 [YouTube https://youtu.be/GlA57dHa5Rg](https://youtu.be/GlA57dHa5Rg) ## 介绍 在本教程中,我们将关注如何开发并使用 `g...
-
Go 中接口值的复制
我一直在思考 Go 语言它是如何工作的。直到最近我才发现 Go 中一切都是基于值的。当我们向函数传递参数、迭代切片、执行类型断言时我们都可以看到这一现象。在这些例子中,这些数据结构所存储的值的拷贝会被返回。当我刚开始学习 Go 的时候,我对于这种实现方式很失望,但渐渐地我开始意识到这样做对于我们的代码来说有它的合理性。 我开始在想,如果我创建了一个所存储的是值而非指针的接口类型的拷贝会发生什么。那么这个新的接口值会拥有自己新的副本值,还是共享原来的值?为了验证我的猜想,我写了一个小程序来检...
-
在 Go 中实现并发性
如果要我从 Go 的特性中选一个最棒的,那么必定是它内置的并发模型。Go 不仅支持并发,而且做的相当好。Go 语言并发模型和并发性的关系就好像是 Docker 和虚拟化一样。 ## 什么是并发? 在计算机编程中,**并发性是计算机同时处理多个任务的能力**。例如,如果您在浏览器中上网,同一时刻可能会发生很多事情。在特定情况下,你可能会在你**当前浏览的网页上**听歌的同时下载一些文件。因此浏览器需要能够同时处理很多事情。如果浏览器无法立即处理它们,您需要等到所有下载完成后再开始浏览互...
-
Go 语言中你应该知道的关于 Package 的所有
*一个 Go 编程语言的包管理及应用的全面概述* 如果你对像 **Java** 或者 **NodeJS** 这样的语言熟悉,那么你可能对**包**(译者注:原文中 **packages** ,后文中将其全部译为中文出现在文章表述中)相当熟悉了。包不是什么其他的,而是一个有着许多代码文件的目录,它从单个引用点显示不同的变量(特征)。让我来解释一下,这是什么意思。 设想在某个项目上工作,你需要不断的修改超过一千个函数。这之中的一些函数有相同的行为。比如,`toUpperCase` 和 `toLo...
-
Go 方法(第二部分)
这篇文章介绍了关于 Go 语言中方法的剩余部分。强烈建议先阅读[第一部分](https://studygolang.com/articles/14061) 的介绍部分。 ## 方法表达式 如果有这样一个类型 T,它的方法集中包含方法 M,则 T.M 会生成一个与方法 M 几乎相同且带有签名的方法,这称为 *方法表达式*。不同之处在于,它额外附带的第一个参数与 M 的接收者类型相等。 ```go package main import ( "fmt" "refle...
-
用 gopher 的方式使用 panic
Go 运行时(即成功编译后,操作系统启动该该进程)发生的错误会以 panics 的形式反馈。*panic* 可以通过这两种形式触发 : 1.直接使用内置 *panic* 函数: ```go package main func main(){ panic("foo") } ``` ``` > go install github.com/mlowicki/lab && ./bin/lab panic: foo goroutine 1 [running...
-
Go 编译器 nil 指针检查
## 简介 我在思考编译器是如何保护我们写的代码。无效的内存访问检查是编译器添加到代码中的一种安全检查。我们可能会认为这种“额外的代码”会损耗程序的性能,甚至可能需要数十亿的迭代操作。但是,这些检查可以防止代码对正在运行的系统造成损害。编译器本质上是指出和查找错误,使我们编写的代码在运行时更安全。 基于上述考虑,同时 Go 语言想要达成更快的编译速度,如果硬件可以解决这些问题,那么 Go 语言编译器就会使用硬件来解决问题。其中一种情况是检测无效的内存访问。有时编译器会在代码中添加 n...
-
理解 Go 编程中的 slice
自从我开始使用 Go 编程以来,slice 的概念和使用一直令人困惑。slice 看起来像一个数组,感觉就像一个数组,但它们不仅仅是一个数组,对我来说是一种全新的概念。我一直在阅读 Go 程序员如何使用 slice,我认为现在终于明白了 slice 的用途。 Andrew Gerrand 撰写了一篇非常棒的关于 slice 的博文: http://blog.golang.org/go-slices-usage-and-internals 没有理由重复 Andrew 所写的一切,...
-
Go 实现安全 cookie
我第一次学习 Go 的时候,已经有了一定的 Web 开发经验,但是直接使用 cookie 的经验还比较少。我之前是用 Rails 的,在 Rails 里面如果要读/写 cookie,并不需要自己去实现所有的安全措施。 如你所见,Rails 偏向于通过默认配置就将大部分事情搞定。你不必去设置 CSRF 反制措施,或者做任何特殊操作来加密 cookie。在较新版本的 Rails 中这一切都默认帮你做好了。 用 Go 开发就完全不同了,这些事情并没有默认帮你做好。所以当你想使用 cooki...
-
Go 中的优雅升级
优化升级背后的想法是在进程运行过程中,在用户无感知的情况下对程序的配置和代码进行更换(升级)。尽管这听起来很危险、容易出错、不可取,并且像是一个馊主意 - 事实上我(的想法)和你一样。 但是,有些时候你的确需要它们。这通常在一个没有负载均衡层的环境中会遇到这种问题。我们在 *Cloudfare* 也遇到了这种情况,这使得我们必须研究这类问题、并尝试、实现各类的解决方案。 ![](https://raw.githubusercontent.com/studygolang/gctt-image...
-
在 Go 中使用 finalizers 比不使用更好
Go 拥有 finalizers,它们支持程序调用一些代码并作为一个对象来进行垃圾回收。然而,很多人不太喜欢 finalizers,并且通常的建议是完全避免它们 ([比如](https://twitter.com/davecheney/status/790343722865090560))。最近,David Crawshaw 在[《Finalizers 惨案》](https://crawshaw.io/blog/tragedy-of-finalizers) 一文中指出 finalizers 的众...
-
我的 Channel 在 Select 语句中的 Bug
我当时正在测试一个已经上线运行的项目的新功能,忽然代码表现得非常糟糕。我看到后很惊讶,后来搞清楚了原因。 接下来提供这份代码的简化版本,包含两个 bug。 ```go package main import ( "fmt" "os" "os/signal" "time" ) var Shutdown bool = false func main() { sigChan := make(chan os.Signal, 1) signal.N...
-
关于 Go 中的 panic 的使用以及误用
Go 采用明确的 error 值和类似异常的 panic 机制的方式作为独有的错误处理机制。在文章中将聚焦于 panic 的设计哲学。尝试去理解来自 Go 团队的冲突 首先,这是一个关于语言设计实用性方面的故事,并对实用主义优缺点做了一些思考。 ## 介绍 错误和异常 (errors and exceptions) 大多数编程语言支持 exception 作为处理 error 的标准方式,比如 Java,Python。虽然方便,但也会带来许多问题,这就是为什么他们不喜欢其他语言...
-
探索 Go 中的错误处理模式
当你学习一种新的编程语言时,可能会存在一个挫败期,就是当你无法使用更熟悉的语言来表达想法的时候。你很自然的想知道为什么语言要设计成这样,很容易误认为(当表达想法遇到困难时)这是语言设计者的失误。这种推理可能会导致你以一种非惯用的方法使用一种语言。 一个挑战我自己观念的内容是如何在 `Go` 中处理错误。概括如下: * `Go` 中的错误是一个实现了 `error` 接口(实现了 `Error()` 函数)的任意类型。 * 函数返回错和返回其它类型没有区别。使用多返回值将错误和正常区...
-
Go 读取控制台输入
这是一个快速简单的教程,主要内容是如何在 Go 程序中读取控制台的输入。在这个教程中,我们将创建一个非常简单的脚本,这个脚本可以读取用户的输入并打印出来。 ## 读取整个句子 我们使用 `while` 循环,在 Go 语言中相当于没有任何参数的 `for` 循环,这样就可以让程序一直运行了。在这个例子中,每次输入一个字符串并按下 `enter` 键,我们会通过 `\n` 这个关键字符来区分字符串,如果你想对比刚才输入的字符串,我们还需要调用 replace 方法来去除掉 `\n` 然...
-
Goroutine 的同步(第三部分)
- 第一部分:https://studygolang.com/articles/14118 - 第二部分:https://studygolang.com/articles/14478 ## mutex 和 sync.Once 介绍 ![image](https://raw.githubusercontent.com/studygolang/gctt-images/master/sync-goroutine/part3-1.jpeg) 假设你的程序中有一个需要某种初始化的功能。...
-
Go 接口(第三部分)
本文介绍的是 Golang 接口主题的另一部分。主要内容包括接口中的方法,接口类型的值作为 map 中的 key,或者作为内置字段。 - 第一部分:https://studygolang.com/articles/14580 - 第二部分:https://studygolang.com/articles/15975 ## 方法和接口 Go 是有方法的概念的。可以通过调用类型 T 中的方法来获得一个函数,此函数可以从类型 T 中额外地获得明确的参数。 ```go typ...
-
Go 语言中的递归和尾调用操作
曾几何时,我看过一段关于 Go 递归函数的简单例子,作者用了极快的速度简单的陈述了 Go 这门语言中并没有优化递归这一操作,即使是在尾调用(tail calls)非常明显的时间。我当时并不理解什么是尾调用(tail calls),我非常想知道这位作者提到的 Go 语言没有优化递归操作的原因是什么,因为我从来不知道原来递归操作还可以被优化。 有些人不太理解什么是递归操作,其实可以用一种简单的说法来解释,就是函数自己调用自己本身。 那为什么我们会需要写一个函数来调用自己本身呢?举个例子,递归算...
-
Go 的多层切片
我是一名程序员,我的工作内容是为美国不同地区的海洋天气预报加载多边形区域(polygons)。这些多边形需要存储在 MongoDB 中,而且还需要作特殊处理。本来也没什么难的,但是每个地区有很多个多边形区域。一个大的多边形区域还包含着 0-n 个多边形,并且它们之间需要维护一定的关系。 看了一会儿问题之后,我意识到我需要创建一个海洋预报地区的切片,每个地区包含一个多边形区域的切片。为了存储每一个多边形环线,我需要一个地理坐标切片。最后,每个坐标需要存储在二维的 float 数组中。 ...
-
Go GC
大家好,我是 Okada([@ocadaruma](https://twitter.com/ocadaruma)),LINE 广告平台团队的成员。我对 Go 的 GC (垃圾收集器)有点感兴趣,甚至还促使我专门写一篇关于它的博客。Go 是一门由 Google 开发,并且支持垃圾收集的编程语言。Go 通过[管道](https://tour.golang.org/concurrency/2) 支持并发。很多的公司,包括 Google,都在使用 Go,LINE 也用 Go 来开发工具和服务。 #...
-
浅析 Go 语言的数字常量
## 概述 Go 语言的常量的实现方法是 Go 的一个亮点。在 Go 的语言规范中的定义[常量规则](http://golang.org/ref/spec#Constants) 是 Go 独有的。 它们在编译器级别提供 Go 所需要的灵活性,使我们编写的代码可读且直观,同时仍保持类型安全。 本文将会探讨”什么是数字常量“、”它们在最简单的情况下时有怎样的行为“以及”怎样去探讨它们才是最好的“这几个方面,其中会有很多吓人的细节问题、名词和概念,所以本文将会放慢速度慢慢的剖析之。 ...
-
Go 语言中的接口 (part II)
## 类型断言 & 类型转换 有些时候,我们需要将数值转换成不同的类型。在编译的时候会进行类型转换的检查,整个机制已经在 [以前的文章](https://medium.com/golangspec/conversions-in-go-4301e8d84067)(GCTT 译文:https://studygolang.com/articles/14018) 中讲过。简而言之它就像下面这样([源代码](https://play.golang.org/p/ogrrsqU6IZ)): ```...
-
宏观看 Go 语言中的 Map 内部
网上有很多涉及 slice 内部的文章,相比之下深入探讨 map 的文章非常稀少,我非常好奇为什么会这样,就去找了这份能深入了解 map 的源码。 https://golang.org/src/runtime/map.go(译者注:因为最新 1.11 版本变更了文件名,所以链接修改为最新的地址。) 这些代码对于我来说很复杂,但是我觉得我们可以用一种宏观的形式去理解 map 是如何构建以及增长。这种方式也许可以解释 map 为什么无序,高效和快速。 **创建和使用 Map** ...
-
Go 程序到机器码的编译之旅
在 [Stream](https://getstream.io/) 里,我们广泛地使用 Go,它也的确巨大地提高了我们的生产效率。我们也发现 Go 语言性能的确出众。自从使用了 Go 以后,我们也完成了类似于我们内部使用的基于 gRPC, Raft 和 RocksDB 存储引擎这类技术栈关键性部分的目标。 今天我们根据 Go 1.11 版本的编译器,来看一下它是如何将我们的 Go 源代码编译成可执行程序的。以此我们能更加了解我们每天工作所用到的工具。我们也会看到为何 Go 语言如此之快并且...
-
在 Go 运行时中的 Strings
## 动机(Motivation) 可以认为这是对 [Rob Pike](https://ai.google/research/people/r) 的一篇关于 Go 字符串的[博客](https://blog.golang.org/strings)的解释。以 Go 程序员的思维来写。 在博客文章中,他说没有什么证据可以证明 Go 字符串是以 slices 的方式实现。我猜这不是他的疏忽,但起码可以证明一点,这不是这篇博客的核心。再说,任何想要自己研究的都可以在使用 Go 代码的过程中...
-
在 Go 中发现竞态条件 (Race Conditions)
当我意识到我一直在处理和解决的问题有一个专有名词描述的时候,我总会觉得这事十分有趣。这次出现这种情况的是竞争条件(Race Conditions)。当你处理多个 routine 共享某类资源的时候,不可避免的需要考虑到这个。如果你未曾在你的代码中考虑过这个问题,现在就是一个不错的时候。 竞争条件是:当两个或两个以上的 routines 访问相同资源的时候,例如一个变量或者结构体,并且在不考虑其他 Gorutines 的情况下对资源进行读/写。这类代码能够造成你所能见到的最令人头疼,最随机的...
-
介绍 Corral:一个无服务器的 MapReduce 框架
这篇文章给出了一个我们最新项目的技术概述和架构设计理由,corral —— 一个无服务的 MapReduce 框架。 我最近在用 Hadoop 和 Spark 为一个我帮助教学的班级工作。PySpark 的确很棒,但是 Hadoop MapReduce 我从来没有真正关注,直到我发现 [mrjob](https://pythonhosted.org/mrjob/)。MapReduce 的观念是极为强大的,但是大量的样板文件需要用 Java 编写,甚至是一个简单的 Hadoop 作业,在我看...
-
Go 中的 import 声明
Go 中的程序由各种包组成。通常,包依赖于其它包,这些包内置于标准库或者第三方。包首先需要被导入才能使用包中的导出标识符。这是通过结构体调用 *import 声明* 来实现的: ```go package main import ( "fmt" "math" ) func main() { fmt.Println(math.Exp2(10)) // 1024 } ``` 上面我们有一个 import 导入的例子,其中包含了两行导入声...
-
webhook 是什么以及如何创建
我们在网上做的工作,大部分其实就是事件,webhooks 已经成为了连接系统的主要方式,不管是用户创建、支付成功、DockerHub 镜像推送或者 Git 仓库上的合并请求,这些都是非常有用并且轻量级的共享信息的方式 ![](https://raw.githubusercontent.com/studygolang/gctt-images/master/webhook/1.png) 那么,webhook 究竟是什么呢?webhook 是应用给其它应用提供实时信息的一种方式。信息一产生...
-
Go 中的数据结构 -- Interface
Go 中的 interface 可以静态编译,动态执行,是最让我感到兴奋的一个特性。如果要让我推荐一个 Go 语言的特性给其他的语言,那我一定会推荐 interface。 本文是我对于 Go 语言中 interface 类型在 gc 编译器上实现的一些想法。Ian Lance Taylor 写了两篇关于 interface 类型在 gccgo 中实现的[文章](https://www.airs.com/blog/archives/277)。本文与之最大的不同是本文有一些图片可以更形象的说明...
-
Go 语言的内存管理
这篇博客是我在维尔纽斯的 [Go Meetup](https://www.meetup.com/Vilnius-Golang/events/249897910/) 演讲的总结。如果你在维尔纽斯并且喜欢 Go 语言,欢迎加入我们并考虑作演讲 在这篇博文中我们将要探索 Go 语言的内存管理,首先让我们来思考以下的这个小程序: ```go func main() { http.HandleFunc("/bar", func(w http.ResponseWriter, r *h...
-
一个好的 Go 语言 Makefile 是怎样的
精简的 Makefile,用于简化构建和管理用 Go 编写的 Web 服务器。 ![](https://raw.githubusercontent.com/studygolang/gctt-images/master/a-good-makefile-for-go/makefile-process.gif) 我偶然调整我的 Makefiles 来加快我的开发过程,一天早上有点时间,我决定与大家分享其中诀窍。 总而言之,我使用 Go 构建 Web 服务器,我对 Makefile 的...
-
Go 语言中的同步队列
## 问题 假设我们在运营一家 IT 公司,公司里面有程序员和测试员。为了给个机会他们互相认识对方,并且让他们能够在工作中放松一点,我们买了一个乒乓球台,并且制定了如下规则: - 每次只能两个人(不能少于或多于两人)玩。 - 只有上一对玩家结束了,下一对玩家才能玩,也就是说,不能只换下一个人。 - 只能是测试员和程序员组成一对来玩,(不能出现两个测试员或者两个程序员一起玩的情况)。如果员工想要玩的话,那么他得等到有合适的对手了才能开始游戏。 ```go func main...
-
我们必须遵循的 12 个 Go 语言最佳实践
本文旨在提供一个切实的指导,在 Go 语言中实现最佳实践和设计模式。这些编程技巧可以帮助开发者编写出较好的代码。你一定已经读过了 [Go Tutorial](https://tour.golang.org/welcome/1) 和 [Effective Go](https://golang.org/doc/effective_go.html)。 为了让大家对这些编程技巧有更加深刻的认识,我在讨论这些最佳实践的时候会附加一些示例代码。 那些编写了许多优秀代码的大师们,一直在使用一些 G...
-
Go 的依赖注入
过去几年里我一直使用 Java。最近,用 Go 建立了一个小项目,然而 Go 生态系统中依赖注入(DI)功能缺乏让我震惊。于是我决定尝试使用 Uber 的 [dig](https://github.com/uber-go/dig) 库来构建我的项目,期间感触颇深。 我发现 DI 帮助我解决了之前在 Go 应用程序中遇到的很多问题 - 过度使用 `init` 函数,滥用全局变量和复杂的应用程序设置等。 在这篇文章中,我将介绍 DI ,然后在使用 DI 框架(通过 `dig` 库)前后写...
-
深入理解 sync.RWMutex:解决读者-写者问题
在某个数据需要被多个线程共享访问的时候,会出现读者-写者问题(这里的「问题」是复数形式的,因为读者-写者问题有多个变种)。访问共享数据的线程有两种类型:读者和写者。读者只会读取数据,而写者则是修改它。当写者拥有了访问数据的权限后,其它的线程(不管是读者还是写者)都不能访问这个数据。这种约束的需求在现实中是存在的,比如:当写者不能原子性地修改某个数据(例如数据库)时,在修改完成之前,要读取这个数据的读者要被阻塞,以免读者获取到损坏的数据(脏数据)。对于读者-写者问题的核心,还有很多修订的限制,比如...
-
在 Go 语言中使用 Log 包
Linux 在许多方面相对于 Windows 来说都是独特的,在 Linux 中编写程序也不例外。标准输出,标准 err 和 null devices 的使用不仅是一个好主意,也是一个原则。如果您的程序将记录日志信息,则最好遵循目标约定。这样,您的程序将兼容所有 Mac/Linux 工具和托管环境。 Go 在标准库中有一个 log 包和 logger 类型。使用 log 包将为您提供成为优秀公民 (译注:指 log 包兼容性非常好) 所需的一切。您将能够写入所有标准设备,自定义文件或支持 ...
-
Go 语言中的 Timer Routines 与优雅退出
在我的 Outcast(译注:作者自己做的一款天气预告 App) 数据服务器中,有几个数据检索任务要用到不同的 Go routine 来运行, 每个 routine 在设定的时间间隔内唤醒。 其中最复杂的工作是下载雷达图像。 它复杂的原因在于:美国有 155 个雷达站,它们每 120 秒拍摄一张新照片, 我们要把所有的雷达图像拼接在一起形成一张大的拼接图。(译注:有点像我们用手机拍摄全景图片时,把多张边缘有重叠的图片拼接成一张大图片) 当 go routine 被唤醒去下载新图像时,它必须尽快为...
-
Go 迭代切片 (Iterating Over Slices In Go)
切片在我的代码中随处可用。如果我正在使用 MongoDB 中的数据,它将存储在切片中。如果我需要在运行操作后跟踪一系列问题,它将存储在一个切片中。如果你还不了解切片是如何工作的,或者像我在开始时一样避免使用切片,请阅读下面这两篇文章以了解更多信息。 [理解 Go 中的 slice](http://www.goinggo.net/2013/08/understanding-slices-in-go-programming.html) [Go 中不定长度集合](https://study...
-
Go 语言中的选择器
在 Go 语言中,表达式 `foo.bar` 可能表示两件事。如果 *foo* 是一个包名,那么表达式就是一个所谓的`限定标识符`,用来引用包 *foo* 中的导出的标识符。由于它只用来处理导出的标识符,*bar* 必须以大写字母开头(译注:如果首字母大写,则可以被其他的包访问;如果首字母小写,则只能在本包中使用): ```go package foo import "fmt" func Foo() { fmt.Println("foo") } func bar() {...
-
使用 Goroutines 池来处理基于任务的操作
*作者注:使用 Go 语言工作了一段时间之后,我学会了如何使用无缓冲 channel 来构建 Goroutines 池,我喜欢这种方式胜于此文章中所展示的方式。话虽如此,此文章在它所描述的场景中依然有巨大价值。* 我在多个场合都被问到为什么使用工作池模式,为什么不在需要的时候启动所需要的 Goroutines?我的答案一直是:受限于工作的类型、你所拥有的计算资源和所处平台的限制,盲目地使用 Goroutines 将会导致程序运行缓慢,进而伤害整个系统的响应和性能。 每个程序、系统和平...
-
Go 程序在 macOS 上的打包功能
这篇文章简单地说明了如何在 macOS 上打包一个 Go 的程序,包括引用或者不引用外部资源。作为一个原生的 Cocoa 程序它是可以下载、安装和运行的。开发过程并不需要 XCode,cgo 或者其他特殊的库文件。 在此文章结尾处,你的 Go 程序将会被打包进一个 `.app` 文件,成为一个拖放安装的只读 DMG 文件。这也适用于其他非 Go 语言的程序。 关于这个端到端的解决方案的主题还有其他很多的指导文章,有的讲的比我想要做的内容多很多,有的又是采用不同的方式,而我想呈现给你的...
-
检测 Go 程序中按值传递的 locks
`go tool vet -copylocks` 命令简介 Go 语言安装包附带 [vet](https://golang.org/cmd/vet/) 命令行工具。该工具能对程序源码运行一套启发式算法以发现可疑的程序结构,如无法执行的代码或对 `fmt.Printf` 函数的错误调用(指 arguments 没有对齐 format 参数): ```go package main import "fmt" func f() { fmt.Printf("%d\n") ...
-
goroutine 的同步(第二部分)
> Channel 通信 第一部分介绍了发送与接收操作之间最直观的顺序关系: > *向一个 Channel 中发送数据先于接收数据。* 于是,我们能够控制分布于两个 goroutine 中的操作的顺序。 ```go var v int var wg sync.WaitGroup wg.Add(2) ch := make(chan int) go func() { v = 1 ch <- 1 wg.Done() }() go fu...
-
用 runtime 包做 Go 应用的基本监控
您可能想知道——特别是如果您刚开始使用 Go,该如何给您的微服务应用添加监控。正如那些有跟踪记录的人告诉您——监控是很困难的。那么我要告诉您的是至少基本的监控不是那样的。您不需要为您的简单应用启动一个 [Prometheus](https://prometheus.io/) 集群去获得报告,事实上,您甚至不需要额外的服务去添加一个您的应用统计的简单输出。 但是我们的应用程序的哪些特性是我们感兴趣的呢?这个 Go 的 [runtime](https://golang.org/pkg/runt...
-
Go 语言中的两种 slice 表达式
在此之前,已经有许多关于 Golang 中 slice 的介绍,比如 * [Go Slices: usage and internals](https://blog.golang.org/go-slices-usage-and-internals) * [How to avoid Go gotchas](https://blog.golang.org/go-slices-usage-and-internals) 本文只是关注于 slice 的表示方式,它们可以创建两种类型的值: ...