This is a creation in Article, where the information may have evolved or changed.
PackageMainImport("Encoding/json""Errors""FMT""Net/http""IO""OS""Path""Io/ioutil""Sync")//TURN-over FM url:http://www.qingting.fm/#/vchannels/136962/programs/5659080//TURN-over FM Ajax address: Http://www.qingting.fm/s/vchannels/136962/programs/5745196/ajaxvarQINGTINGAJAXADDRFMT ="Http://www.qingting.fm/s/vchannels/%d/programs/%d/ajax"parsing of JSON in//go language, if there is no fixed input format, try to use common format map [] interface{}//Because the Go language export structure is capitalized by default and needs to correspond to the actual format, it is better to use map+interface+[]//type qingtingsongsubitem struct {//Name string "Song name"//ParentName string "album name"//Qtsongs []string "Song url"//ParentID int "Parent directory ID"//Duration int "duration"//Type string "type"//ID int "type"//Thumb string "thumbnail"//}////type qingtingsongitem struct {//Playinfo Qingtingsongsubitem//}////type qingtingplayinfo Qingtingsongitem////func (This *qingtingplayinfo) Download (dirname string) (bool, error) {//return false, nil//}////func (This *qingtingplayinfo) String () string{//Return FMT. Sprintf ("Song Name:% #v Album name:% #v song URL address:% #v Parent directory id:% #v Duration:% #v Type:% #v thumbnail:% #v",//this. Playinfo.name,//this. Playinfo.parentname,//this. Playinfo.qtsongs,//this. Playinfo.parentid,//this. Playinfo.duration,//this. Playinfo.type,//this. Playinfo.id,//this. PLAYINFO.THUMB)//}typeQingtingplayinfoMap[String]Interface{}funcDownload (This qingtingplayinfo, dirname string, WG *sync. Waitgroup) (bool, error) {deferWg. Done ()//pthis: = (map[string]interface{}) (this) Name: = this["Name"]. (string) URL: ="Http://od.qingting.fm"+ this["URLs"]. ([]Interface{})[0]. (string) FileName: = path. Join (DirName, name+". m4a") FMT. Printf ("Start Download:%s to:%s\n", URL, filename) res, err: = http. Get (URL)ifErr! = nil{FMT. Printf ("Download error:%s\n", err)returnFalse,err}deferRes. Body.close () data, err: = Ioutil. ReadAll (Res. Body)ifErr! = nil{FMT. Printf ("Download failed:%s\n", err)returnFalse,err} ERR2: = Ioutil. WriteFile (filename, data,0666)ifErr2! = nil{FMT. Printf ("Download failed:%s\n", ERR2)returnFalse, ERR2} FMT. Printf ("!!! Download succeeded:%s to:%s\n ", URL, filename)returnTrue, nil}//-----------------------------------------------------------------typeQingtingfmstruct{Channel int"Channel" ID int"Channel ID"}func(This *QINGTINGFM) Crawl () ([]qingtingplayinfo, error) {jsonbyte, err: = This.readjson ()ifErr! = Nil {returnNil, err}ifJsonbyte = = nil{returnNil,errors. New ("Invalid data returned") }//go Language and JSON mapping relationship: corresponding structure data [] corresponding array PiS: = Make ([]qingtingplayinfo,0) Jerr: = json. Unmarshal (Jsonbyte, &pis)ifJerr! = nil{returnNil,jerr} Downloaddir: ="Music_go" Os. Mkdirall (Downloaddir,0666)//for _,pi: = Range pis{//FMT. Println (pi["name"]) //} varWG Sync. WaitgroupMaximum number of connection caches// Maxindex: = Len (PiS)-1 Cachemax: =5 forI,PI: =Rangepis{WG. ADD (1) cachemax++//WG must be a reference, there must be a limit to the number of async, or too many connections to the server, the server will reject, resulting in a download failure GoDownload (Pi,downloaddir, &WG)//Use cache ifCachemax >5|| Maxindex = = i{WG. Wait () Cachemax =0 } }returnPiS, nil}func(This *QINGTINGFM) Readjson ([]byte, error) {//ajaxaddr: = "http://www.golangtc.com/t/533c0ad2320b520cc400004f"//http. Get automatic gzip decompression data stream Res, ERR: = http. Get (THIS.GETAAJXADDR ())ifErr! = Nil {returnNil, err} readercloser: = Res. Body//need to close after reading deferReadercloser.close ()offRes. StatusCode! = ${returnNil, errors. New ("Return error status Code")} Bytes: = Make ([]byte,0,1024x768)//buffer must be an array, or you can use Ioutil ReadAll to read varBuffera [ -]byte buffer: = buffera[:] for{readed, Rerr: = readercloser.read (buffer)ifreaded = =0&& Rerr = = nil{returnNil, errors. New ("Readed=0 Rerr=nil") }//Slice ..., automatically unzip the array into a number of parameter inputs//implementation principle and ..., the same principle as the argument support//This sentence should be in ==io. EOF, if you write to the back, you lose the last part of the data bytes = append (bytes,buffer[:readed] ...)//Data stream read Complete ifRerr = = Io. eof{ Break }ifRerr! = Nil {returnNil, Rerr}}//Convert bytes to string returnBytes, nil}func(This *QINGTINGFM) getaajxaddr () string {returnFmt. Sprintf (QINGTINGAJAXADDRFMT, this. Channel, This.id)}//-----------------------------------------------------------------funcMain () {qtfm: = Qingtingfm{channel:136962Id:5745196} QTFM. Crawl ()}