Moral integrity, code, accomplishment, sister and others (go language)

Source: Internet
Author: User
Tags close close sendloop sendmsg try catch
This is a creation in Article, where the information may have evolved or changed.

Festival & Fuck, Coding, Inner depth, Sister and Others.

Some articles will mention why the go language is so unpopular, there is really no need to waste my mind on go language, why I give up go language, why worse is better, and other topics. Revisit these topics regularly and find new discoveries every time. The most taboo hand has a language, the heart will not tolerate another language.

Ignore the details, grammar or design, the go language is useful. Given these factors, go is not too far to be sprayed.

This article is not intended to be a matter of detail, grammar or design, just to give some examples of how to write the code in the go language that makes sense.

Classes, objects, attributes, and possibly a little bit of design pattern

code from HTTPS://GITHUB.COM/XGDAPG/XCONN/BLOB/MASTER/XCONN.GO, verified//conn corresponds to a TCP connection type Conn struct {//native TCP connection Conn Net.    Conn//Transmit data channel (similar queue) send Chan *msgdata//Message processing method Msghandler Msghandler//tcp Buffer Recvbuffer []byte//message once package, subsequent two package msgpacker msgpacker//Health Check cycle pinginterval UINT//Jian Kang Check method Pinghandler Pinghandler//Stop Health Check channel Pingstop chan bool//Customize the method that is called when the connection is closed Closehandler Closehandler}//msghandler for custom processing messages type Msghandler interface {handlemsg (*msgdata)}//msgpacker is a custom unpacking package, For performance you can merge this segment directly with the Recvloop side type Msgpacker interface {packmsg (*msgdata) []byte unpackmsg ([]byte) *msgdata}//msgdata Custom Type msgdata struct {Data []byte Ext interface{}}//pinghandler for custom heartbeat command type Pinghandler interface {Handlepi Ng ()}//closehandler for a custom action when the connection is broken type Closehandler interface {handleclose ()}//newconn to handle the new connection mode: Start two coprocessor, one is only responsible for reading, one is only responsible for writing, It can also be considered that three processes are enabled and the third is responsible for timing piNg Operation Func Newconn (Conn net. Conn) *conn {c: = &conn{conn:conn, Send:make (Chan *msgdata, +), Msghandle        R:nil, Recvbuffer: []byte{}, Msgpacker:nil, pinginterval:0, Pinghandler:nil, Pingstop:nil, Closehandler:nil,} go C.recvloop () go C.sendloop () return c}//recoverpanic program pan The processing method in the case of an IC (e.g. writing data to a TCP connection that has been closed causes panic) func Recoverpanic () {if err: = Recover (); Err! = nil {//fmt. PRINTLN (Err)}}//setmsghandler for Getter Setter method func (this *conn) Setmsghandler (Hdlr msghandler) {This.msghandler = Hdlr}//setmsgpacker for Getter Setter method func (this *conn) Setmsgpacker (packer msgpacker) {This.msgpacker = Packer}//se Tping for Getter Setter method func (this *conn) setping (sec uint, HDLR pinghandler) {this.pinginterval = sec This.pinghan Dler = HDLR if this.pingstop = = Nil {this.pingstop = make (chan bool)} if sec > 0 {go this.pin Gloop ()}}//setclosehandler for Getter Setter method func (this *conn) Setclosehandler (Hdlr closehandler) {This.closehandler = hdlr}// Pingloop for timed Health Check operation func (this *conn) Pingloop () {defer recoverpanic () for {select {case <-this.pi Ngstop:return case <-time. After (time. Duration (this.pinginterval) * time. Second): this. Ping ()}}}//rawconn returns the original TCP connection func (this *conn) rawconn () net. Conn {return this.conn}//recvloop is used to process the received TCP packet, and then the operations such as unpacking, and then calling the Recvmsg method to process func (this *conn) Recvloop () {defer Recov Erpanic () defer this.    Close () Buffer: = Make ([]byte, 2048)//Packet Protocol: four bytes (Int32) represents the packet length, which intercepts the message length as a package based on packet length. For {bytesread, err: = This.conn.Read (buffer) if err! = nil {return} This.recvbu        Ffer = Append (This.recvbuffer, Buffer[0:bytesread] ...) For Len (This.recvbuffer) > 4 {length: = binary.       Bigendian.uint32 (This.recvbuffer[0:4]) Readtoptr: = length + 4     If UInt32 (Len (this.recvbuffer)) < readtoptr {break} if length = = 0 { If This.pinghandler! = nil {this.pingHandler.HandlePing ()}} else {buf: = This.recvbuffer[4:readtoptr] Go this.recvmsg (BUF)} THIS.RECV Buffer = this.recvbuffer[readtoptr:]}}}//recvmsg is a proxy and is actually performing the Handlemsg method in the background. Func (this *conn) recvmsg (data []byte) {defer recoverpanic () msg: = &msgdata{data:data, ext:n  IL,}//Call unackmsg to unpack the information two times if this.msgpacker! = Nil {msg = THIS.MSGPACKER.UNPACKMSG (data)} if This.msghandler! = nil {this.msgHandler.HandleMsg (msg)}}//sendloop used to send packet func (this *conn) Sendloop () {D Efer Recoverpanic () for {msg, OK: = <-this.send if!ok {break} go This.sen Dmsg (msg)}}//sendmsg is used to send packets, actually calls packmsg for information persistence, and then two packets,Convert to this framework can accept form func (this *conn) sendmsg (msg *msgdata) {defer recoverpanic () Sendbytes: = Make ([]byte, 4) if msg! = Nil {data: = Msg.        Data if this.msgpacker! = Nil {data = THIS.MSGPACKER.PACKMSG (msg)} Length: = Len (data) Binary.    Bigendian.putuint32 (sendbytes, UInt32 (length)) sendbytes = append (sendbytes, data ...) } this.conn.Write (sendbytes)}//close Close connection func (this *conn) close () {defer recoverpanic () This.conn.Close () cl OSE (this.send) if this.pingstop! = nil {close (this.pingstop)} if This.closehandler! = Nil {this. Closehandler.handleclose ()}}//sendmsg used to send data func (this *conn) sendmsg (msg *msgdata) {this.send <-Msg}//senddat A is used to send data func (this *conn) senddata (data []byte) {this. Sendmsg (&msgdata{data:data, Ext:nil})}//ping for health monitoring func (this *conn) Ping () {go this.sendmsg (nil)}

As a framework dedicated to dealing with TCP links, in fact Xconn (the code above) has been encapsulated two times, and even message sending, message unpacking, and even receiving information have been encapsulated two times.

In the actual code, you can simplify the operation by simplifying the section two times to one time.

Write the code as neatly as above, and it has gone beyond most apes.

In the last example, the author used the recover, restrained, but just right.

As for defer and panic

Try catch for Go language?

import (    "fmt"    "github.com/manucorporat/try")func main() {    try.This(func() {        panic("my panic")    }).Finally(func() {        fmt.Println("this must be printed after the catch")    }).Catch(func(e try.E) {        // Print crash        fmt.Println(e)    })}

The above code is purely funny, the individual does not recommend the use of the project in this way, but this practice can be used for reference.

Project code: (for Go and database transaction)

//代码来自《Go语言游戏项目应用情况汇报》func (db *Database) Transaction(work func()) {    db.lock.Lock()    defer db.lock.UnLock()    //事务控制    defer func() {        if err := recover; err == nil {            db.commit(info)        } else {            db.rollback()            //选择性抛出panic            panic(TransError{err})        }    }()    //执行传入的函数    work()}

"Go Language Game Project Application Report" is what I can find, a few dare to open some of the project code sharing. Overall code is neat, suitable for beginners to learn.

The above method of dealing with err, and "Errors is the values" has the same similar wonderful.

One way to handle err

Model code: From "Errors is Vales"

//这种写法强烈不推荐!!!!这就是许多人说的Go程序一大半都在check error_, err = fd.Write(p0[a:b])if err != nil {    return err}_, err = fd.Write(p1[c:d])if err != nil {    return err}_, err = fd.Write(p2[e:f])if err != nil {    return err}// and so on//重要的事情说两遍:不推荐,但是个人小项目这样写,完全没问题。

We recommend the following wording:

var err errorwrite := func(buf []byte) {    if err != nil {        return    }    _, err = w.Write(buf)}write(p0[a:b])write(p1[c:d])write(p2[e:f])// and so onif err != nil {    return err}

The following wording is also recommended:

func (ew *errWriter) write(buf []byte) {    if ew.err != nil {        return    }    _, ew.err = ew.w.Write(buf)}

Other:

Justify: Why choose the Go language.

A: Because it's simple, and it won't be anything else.

Suggestion: try to choose Go1.6 and above, avoid GC cause program STW.

As for GC performance, can you refer to GC pause in Go1.6 that has completely overtaken the JVM?

The original text is forbidden to reprint, so refining the keyword: from the effect to see XXX, but xxx; and, xxx,xxx.

So, why worse is better?

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.