论golang的文档即代码
来源:互联网 发布:python开发量化交易 编辑:程序博客网 时间:2024/06/04 04:03
GO TEST
如果提供一个库,或者提供了一个模块,如何给使用者描述这个API的用法?一般都是给文档,但是文档非常容易不同步,在golang中,有更高级的做法,也是最好的做法。
以go-fdkaac
为例,这个是一个go binding,调用了lib-fdkaac的c函数,提供aac的codec的一个库。
首先,由于用静态库的方式引用,涉及到了如何下载fdkaac的c代码和编译,需要在doc中说明,也就是README.md中说明Usage
:https://github.com/winlinvip/go-fdkaac#usage
在Usage中,准备好代码和环境后,就只需要链接到使用的examples:
- 解码使用实例,如何使用AAC解码器。
而这个使用说明本身就是utest,有期望值,可以运行:
winlin:go-fdkaac winlin$ go test ./...? github.com/winlinvip/go-fdkaac [no test files]ok github.com/winlinvip/go-fdkaac/dec 0.008swinlin:go-fdkaac winlin$
文档变成了可以执行的代码,或者说,没有了经常变化的文档,只有代码,golang这点做得真是perfect!
而example的package,和API的package是不一样的。这个和utest是不一样的,utest因为要访问package内部的内容,所以和API同一个package,比较方便。example因为是给用户用的例子,当然和API的package不能一样,也不可能一样。
GOLANG的Example,强迫API设计者,能从User角度出发,将API设计得很简单易懂,因为复杂的API不好用在写Example时很容易就发现了:
package dec_testimport ( "fmt" "github.com/winlinvip/go-fdkaac/dec")func ExampleAacDecoder_RAW() { var err error d := dec.NewAacDecoder() asc := []byte{0x12, 0x10} if err := d.InitRaw(asc); err != nil { fmt.Println("init decoder failed, err is", err) return } defer d.Close() // directly decode the frame to pcm. var pcm []byte if pcm,err = d.Decode([]byte{ 0x21, 0x17, 0x55, 0x35, 0xa1, 0x0c, 0x2f, 0x00, 0x00, 0x50, 0x23, 0xa6, 0x81, 0xbf, 0x9c, 0xbf, 0x13, 0x73, 0xa9, 0xb0, 0x41, 0xed, 0x60, 0x23, 0x48, 0xf7, 0x34, 0x07, 0x12, 0x53, 0xd8, 0xeb, 0x49, 0xf4, 0x1e, 0x73, 0xc9, 0x01, 0xfd, 0x16, 0x9f, 0x8e, 0xb5, 0xd5, 0x9b, 0xb6, 0x49, 0xdb, 0x35, 0x61, 0x3b, 0x54, 0xad, 0x5f, 0x9d, 0x34, 0x94, 0x88, 0x58, 0x89, 0x33, 0x54, 0x89, 0xc4, 0x09, 0x80, 0xa2, 0xa1, 0x28, 0x81, 0x42, 0x10, 0x48, 0x94, 0x05, 0xfb, 0x03, 0xc7, 0x64, 0xe1, 0x54, 0x17, 0xf6, 0x65, 0x15, 0x00, 0x48, 0xa9, 0x80, 0x00, 0x38}); err != nil { fmt.Println("decode failed, err is", err) return } fmt.Println("SampleRate:", d.SampleRate()) fmt.Println("FrameSize:", d.FrameSize()) fmt.Println("NumChannels:", d.NumChannels()) fmt.Println("AacSampleRate:", d.AacSampleRate()) fmt.Println("Profile:", d.Profile()) fmt.Println("AudioObjectType:", d.AudioObjectType()) fmt.Println("ChannelConfig:", d.ChannelConfig()) fmt.Println("Bitrate:", d.Bitrate()) fmt.Println("AacSamplesPerFrame:", d.AacSamplesPerFrame()) fmt.Println("AacNumChannels:", d.AacNumChannels()) fmt.Println("ExtensionAudioObjectType:", d.ExtensionAudioObjectType()) fmt.Println("ExtensionSamplingRate:", d.ExtensionSamplingRate()) fmt.Println("NumLostAccessUnits:", d.NumLostAccessUnits()) fmt.Println("NumTotalBytes:", d.NumTotalBytes()) fmt.Println("NumBadBytes:", d.NumBadBytes()) fmt.Println("NumTotalAccessUnits:", d.NumTotalAccessUnits()) fmt.Println("NumBadAccessUnits:", d.NumBadAccessUnits()) fmt.Println("SampleBits:", d.SampleBits()) fmt.Println("PCM:", len(pcm)) // Output: // SampleRate: 44100 // FrameSize: 1024 // NumChannels: 2 // AacSampleRate: 44100 // Profile: 1 // AudioObjectType: 2 // ChannelConfig: 2 // Bitrate: 31352 // AacSamplesPerFrame: 1024 // AacNumChannels: 2 // ExtensionAudioObjectType: 0 // ExtensionSamplingRate: 0 // NumLostAccessUnits: 0 // NumTotalBytes: 91 // NumBadBytes: 0 // NumTotalAccessUnits: 1 // NumBadAccessUnits: 0 // SampleBits: 16 // PCM: 4096}
这个API设计时,最初是和fdkaac一样,有Fill([]byte)然后是Decode(),分成了两步,可以多次Fill。后来发现这个实在不好用,不如直接Decode([]byte),可以用Decode(nil)进去。
- 论golang的文档即代码
- 飘逸的python - 代码即文档docstring
- 文档即编码(一):好设计不是好代码
- golang: 官博译文:可测试的 Golang 代码示例
- pHP 请求即下载文件的代码
- 关于代码即设计的随想
- Golang 计算目录中代码的行数
- 一段Golang代码引发的思考
- [golang]反射的用处--代码自动生成
- 使用Delve进行Golang代码的调试
- GoLang代码包的开发详细记录
- 文档即测试
- 测试即是文档
- golang官方学习文档
- Golang标准库文档
- golang 解析word文档
- 单文档程序一运行即最大化窗口的方法
- 我终于理解了LISP『代码即数据|数据即代码』的含义
- Unable to load native-hadoop library for your platform
- Android NavigationDrawer实现
- 数据库日志——Undo | Redo
- Android Activity/Fragment Lifecycle
- arm mini2440 基于v4l2 ffmpeg x264的视频远程监控 ----fwqlzz love is for ever
- 论golang的文档即代码
- 复旦的北大校友名单
- upx加壳原理
- jquery操作select(取值,设置选中)
- MySql插入中文数据,乱码问题的解决
- springMVC中web.xml配置详解
- HBase单机环境搭建及入门
- C# 将两个不同的dataTable合并到一个自定义的dataTable中
- Java EE中Ajax技术实例