This is a creation in Article, where the information may have evolved or changed.
GO TEST
If a library is provided, or a module is provided, how do you describe the usage of this API to the user? The document is usually given, but the document is very easy to get out of sync, and in Golang, there is a more advanced approach and the best practice.
go-fdkaacFor example, this is a go binding that invokes the C function of LIB-FDKAAC, which provides a library of AAC's codec.
First, due to the use of static library reference, it involves how to download FDKAAC C code and compile, need to be explained in Doc, that is readme.md description Usage : https://github.com/winlinvip/go-fdkaac#usage
In usage, once you have the code and environment ready, you only need to link to the examples used:
- Decode the usage instance and how to use the AAC decoder.
And this use note itself is utest, has the expectation, can run:
winlin:go-fdkaac winlin$ go test ./...? github.com/winlinvip/go-fdkaac [no test files]ok github.com/winlinvip/go-fdkaac/dec 0.
The document becomes code that can be executed, or, without the frequently changing documents, only the code, Golang this is really perfect!
The example package is not the same as the API package. This and utest is not the same, utest because to access the contents of the package, so the same package with the API, more convenient. Example because it is for the user's example, of course, and the API package can not be the same, not the same.
Golang's example, forcing the API designer to be able to design the API very easily from the user point of view, because the complex API is not good for writing example easily found:
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:44100Framesize:1024x768Numchannels:2Aacsamplerate:44100Profile:1Audioobjecttype:2Channelconfig:2Bitrate:31352Aacsamplesperframe:1024x768Aacnumchannels:2Extensionaudioobjecttype:0Extensionsamplingrate:0Numlostaccessunits:0Numtotalbytes: theNumbadbytes:0Numtotalaccessunits:1Numbadaccessunits:0Samplebits: -Pcm:4096}
The API was originally designed to be like FDKAAC, with fill ([]byte) and then decode (), divided into two steps that can be fill multiple times. Later found this is not good, rather than direct decode ([]byte), you can use decode (nil) in.