Go语言高级编程
  • Go语言高级编程(Advanced Go Programming)
  • 第1章 语言基础
    • 1.1 Go语言创世纪
    • 1.2 Hello, World 的革命
    • 1.3 数组、字符串和切片
    • 1.4 函数、方法和接口
    • 1.5 面向并发的内存模型
    • 1.6 常见的并发模式
    • 1.7 错误和异常
    • 1.8 补充说明
  • 第2章 CGO编程
    • 2.1 快速入门
    • 2.2 CGO基础
    • 2.3 类型转换
    • 2.4 函数调用
    • 2.5 内部机制
    • 2.6 实战: 封装qsort
    • 2.7 CGO内存模型
    • 2.8 C++类包装
    • 2.9 静态库和动态库
    • 2.10 编译和链接参数
    • 2.11 补充说明
  • 第3章 汇编语言
    • 3.1 快速入门
    • 3.2 计算机结构
    • 3.3 常量和全局变量
    • 3.4 函数
    • 3.5 控制流
    • 3.6 再论函数
    • 3.7 汇编语言的威力
    • 3.8 例子:Goroutine ID
    • 3.9 Delve调试器
    • 3.10 补充说明
  • 第4章 RPC和Protobuf
    • 4.1 RPC入门
    • 4.2 Protobuf
    • 4.3 玩转RPC
    • 4.4 gRPC入门
    • 4.5 gRPC进阶
    • 4.6 gRPC和Protobuf扩展
    • 4.7 pbgo: 基于Protobuf的框架
    • 4.8 grpcurl工具
    • 4.9 补充说明
  • 第5章 Go和Web
    • 5.1 Web开发简介
    • 5.2 请求路由
    • 5.3 中间件
    • 5.4 请求校验
    • 5.5 和数据库打交道
    • 5.6 服务流量限制
    • 5.7 大型Web项目分层
    • 5.8 接口和表驱动开发
    • 5.9 灰度发布和A/B测试
    • 5.10 补充说明
  • 第6章 分布式系统
    • 6.1 分布式 id 生成器
    • 6.2 分布式锁
    • 6.3 延时任务系统
    • 6.4 分布式搜索引擎
    • 6.5 负载均衡
    • 6.6 分布式配置管理
    • 6.7 分布式爬虫
    • 6.8 补充说明
  • 附录
    • 附录A: Go语言常见坑
    • 附录B: 有趣的代码片段
    • 附录C: 作者简介
Powered by GitBook
On this page
  • 自重写程序
  • 三元表达式
  • 禁止 main 函数退出的方法
  • 基于管道的随机数生成器
  • Assert测试断言

Was this helpful?

  1. 附录

附录B: 有趣的代码片段

Previous附录A: Go语言常见坑Next附录C: 作者简介

Last updated 5 years ago

Was this helpful?

这里收集一些比较有意思的Go程序片段。

自重写程序

UNIX/Go语言之父 Ken Thompson 在1983年的图灵奖演讲 Reflections on Trusting Trust 就给出了一个C语言的自重写程序。

最短的C语言自重写程序是 Vlad Taeerov 和 Rashit Fakhreyev 的版本:

main(a){printf(a="main(a){printf(a=%c%s%c,34,a,34);}",34,a,34);}

下面的Go语言版本自重写程序是 提供的:

/* Go quine */
package main

import "fmt"

func main() {
    fmt.Printf("%s%c%s%c\n", q, 0x60, q, 0x60)
}

var q = `/* Go quine */
package main

import "fmt"

func main() {
    fmt.Printf("%s%c%s%c\n", q, 0x60, q, 0x60)
}

var q = `

在 golang-nuts 中还有很多版本:

package main;func main(){c:="package main;func main(){c:=%q;print(c,c)}";print(c,c)}
package main;func main(){print(c+"\x60"+c+"\x60")};var c=`package main;func main(){print(c+"\x60"+c+"\x60")};var c=`

如果有更短的版本欢迎告诉我们。

三元表达式

func If(condition bool, trueVal, falseVal interface{}) interface{} {
    if condition {
        return trueVal
    }
    return falseVal
}

a, b := 2, 3
max := If(a > b, a, b).(int)
println(max)

禁止 main 函数退出的方法

func main() {
    defer func() { for {} }()
}

func main() {
    defer func() { select {} }()
}

func main() {
    defer func() { <-make(chan bool) }()
}

基于管道的随机数生成器

随机数的一个特点是不好预测。如果一个随机数的输出是可以简单预测的,那么一般会称为伪随机数。

func main() {
    for i := range random(100) {
        fmt.Println(i)
    }
}

func random(n int) <-chan int {
    c := make(chan int)
    go func() {
        defer close(c)
        for i := 0; i < n; i++ {
            select {
            case c <- 0:
            case c <- 1:
            }
        }
    }()
    return c
}

基于select语言特性构造的随机数生成器。

Assert测试断言

type testing_TBHelper interface {
    Helper()
}

func Assert(tb testing.TB, condition bool, args ...interface{}) {
    if x, ok := tb.(testing_TBHelper); ok {
        x.Helper() // Go1.9+
    }
    if !condition {
        if msg := fmt.Sprint(args...); msg != "" {
            tb.Fatalf("Assert failed, %s", msg)
        } else {
            tb.Fatalf("Assert failed")
        }
    }
}

func Assertf(tb testing.TB, condition bool, format string, a ...interface{}) {
    if x, ok := tb.(testing_TBHelper); ok {
        x.Helper() // Go1.9+
    }
    if !condition {
        if msg := fmt.Sprintf(format, a...); msg != "" {
            tb.Fatalf("Assertf failed, %s", msg)
        } else {
            tb.Fatalf("Assertf failed")
        }
    }
}

func AssertFunc(tb testing.TB, fn func() error) {
    if x, ok := tb.(testing_TBHelper); ok {
        x.Helper() // Go1.9+
    }
    if err := fn(); err != nil {
        tb.Fatalf("AssertFunc failed, %v", err)
    }
}
rsc