什么是现货期权合约交易所系统开发丨现货期权合约交易所系统开发详解技术

2022-08-07 15:53:51 浏览数 (1)

通过mux定义了两个Handler,URL都是/,但是对应的Method是不一样的。

GET方法通过handleGetBlockchain函数实现,用于获取区块链的信息。

代码语言:javascript复制
func handleGetBlockchain(w http.ResponseWriter, r *http.Request) {
    bytes, err := json.MarshalIndent(Blockchain, "", "  ")
    if err != nil {
        http.Error(w, err.Error(), http.StatusInternalServerError)
        return
    }
    io.WriteString(w, string(bytes))
}

Blockchain是一个[]BlockhandleGetBlockchain函数的作用是把Blockchain格式化为JSON字符串,然后显示出来。io.WriteString是一个很好用的函数,可以往Writer里写入字符串。更多参考 Go语言实战笔记(十九)| Go Writer 和 Reader

'POST'方法通过handleWriteBlock函数实现,用于模拟区块的生成。

代码语言:javascript复制
func handleWriteBlock(w http.ResponseWriter, r *http.Request) {
    w.Header().Set("Content-Type", "application/json")

    //使用了一个Mesage结构体,更方便的存储BPM
    var msg Message

    //接收请求的数据信息,类似{"BPM":60}这样的格式
    decoder := json.NewDecoder(r.Body)
    if err := decoder.Decode(&msg); err != nil {
        respondWithJSON(w, r, http.StatusBadRequest, r.Body)
        return
    }
    defer r.Body.Close()

    //控制并发,生成区块链,并且校验
    mutex.Lock()
    prevBlock := Blockchain[len(Blockchain)-1]
    newBlock := generateBlock(prevBlock, msg.BPM)

    //校验区块链
    if isBlockValid(newBlock, prevBlock) {
        Blockchain = append(Blockchain, newBlock)
        spew.Dump(Blockchain)
    }
    mutex.Unlock()

    //返回新的区块信息
    respondWithJSON(w, r, http.StatusCreated, newBlock)

}

以上代码我进行了注释,便于理解。主要是通过POST发送一个{"BPM":60}格式的BODY来添加区块,如果格式正确,那么就生成区块进行校验,合格了就加入到区块里;如果格式不对,那么返回错误信息。

用于控制并发的锁可以参考Go语言实战笔记(十七)| Go 读写锁

这个方法里有个Message结构体,主要是为了便于操作方便。

代码语言:javascript复制
// Message takes incoming JSON payload for writing heart rate
type Message struct {
    BPM int
}

返回的JSON信息,也被抽取成了一个函数respondWithJSON,便于公用。

代码语言:javascript复制
func respondWithJSON(w http.ResponseWriter, r *http.Request, code int, payload interface{}) {
    response, err := json.MarshalIndent(payload, "", "  ")
    if err != nil {
        w.WriteHeader(http.StatusInternalServerError)
        w.Write([]byte("HTTP 500: Internal Server Error"))
        return
    }
    w.WriteHeader(code)
    w.Write(response)
}

好了,快完成了,以上Web的Handler已经好了,现在我们要启动我们的Web服务了。

代码语言:javascript复制
// web server
func run() error {
    mux := makeMuxRouter()
    //从配置文件里读取监听的端口
    httpPort := os.Getenv("PORT")
    log.Println("HTTP Server Listening on port :", httpPort)
    s := &http.Server{
        Addr:           ":"   httpPort,
        Handler:        mux,
        ReadTimeout:    10 * time.Second,
        WriteTimeout:   10 * time.Second,
        MaxHeaderBytes: 1 << 20,
    }

    if err := s.ListenAndServe(); err != nil {
        return err
    }

    return nil
}

和原生的http.Server基本一样,应该比较好理解。mux其实也是一个Handler,这就是整个Handler处理链。现在我们就差一个main主函数来启动我们整个程序了。

代码语言:javascript复制
//控制并发的锁
var mutex = &sync.Mutex{}

func main() {
    //加载env配置文件
    err := godotenv.Load()
    if err != nil {
        log.Fatal(err)
    }

    //开启一个goroutine生成一个创世区块
    go func() {
        t := time.Now()
        genesisBlock := Block{}
        genesisBlock = Block{0, t.String(), 0, calculateHash(genesisBlock), ""}
        spew.Dump(genesisBlock)

        mutex.Lock()
        Blockchain = append(Blockchain, genesisBlock)
        mutex.Unlock()
    }()
    log.Fatal(run())

}

整个main函数并不太复杂,主要就是加载env配置文件,开启一个go协程生成一个创世区块并且添加到区块链的第一个位置,然后就是通过run函数启动Web服务。

一个区块链都有一个创世区块,也就是第一个区块。有了第一个区块我们才能添加第二个,第三个,第N个区块。创世区块因为是第一个区块,所以它是没有PrevHash的。

0 人点赞