实现一个简易的“状态机”
server # go run server.go 2013/06/06 14:10:11 counterB timedout //超时10秒总和未达到10 client # go run client.go counterA 1 Continue client # go run client.go counterA 3 Continue client # go run client.go counterA 3 Continue client # go run client.go counterA 4 //counterA十秒内数字和>10 Done client # go run client.go counterB 4 //超时10秒总和未达到10 Continue
用go自带的库实现http服务器端server.go:
package main import ( "fmt" "net/http" "log" "os" // "os/signal" "g10086" "bufio" "io" "strings" "time" "encoding/json" "strconv" // "syscall" ) //g10086 location 记录的配置文件 const g10086_save = "g10086.status" //查看当前g10086的全局状态信息 func rootHandler (w http.ResponseWriter, r * http.Request) { fmt.Fprintf(w, "g_status: %d\n", len(g10086.G_status)) for key,val := range g10086.G_status { fmt.Fprintf(w, "%s : %s\n", key, val) } } //将全局状态信息表存储到文件中 func saveHandler (w http.ResponseWriter, r * http.Request) { save_status() io.WriteString(w, "Save OK!") } //从文件加载信息 func load_status () { g10086.G_status = make(map[string] string) f, err := os.OpenFile(g10086_save, os.O_RDWR|os.O_CREATE, 0666) if err != nil { log.Fatal(err) } defer f.Close() r := bufio.NewReader(f) line, _, err := r.ReadLine() for err == nil { if info := strings.Split(string(line)," "); len(info) > 1 { g10086.G_status[info[0]] = info[1] } line, _, err = r.ReadLine() } } func save_status () { f, err := os.OpenFile(g10086_save, os.O_CREATE|os.O_RDWR, 0666) if err != nil { log.Fatal(err) } defer f.Close() b := bufio.NewWriter(f) for key,value := range g10086.G_status { line := key + " " + value + "\n" if n, err := b.WriteString(line); err != nil || n != len(line) { log.Fatal(err) } } if err = b.Flush(); err != nil { log.Fatal(err) } } //查看全局状态信息是否有超时的信息,如果有,删除并记录日志 func check_timeout() { cur := time.Now().Unix() for key,value := range g10086.G_status { var cur_down g10086.Dstate //不能放在for循环之前! dec := json.NewDecoder(strings.NewReader(value)) if err := dec.Decode(&cur_down); err != nil { return } for k,_ := range cur_down.Info { t, err := strconv.Atoi(k) if err != nil { return } if t < int(cur - 10) { delete(g10086.G_status, key) log.Println(key + " timedout") break } } } } //定时器,每1秒钟运行一次,检测超时 func timer () { for { timer := time.NewTicker(1 * time.Second) for { select { case <- timer.C: check_timeout() } } } } //配置服务器,监听端口和location func main () { load_status () go timer() defer save_status() http.HandleFunc("/",rootHandler) http.HandleFunc("/g10086",g10086.G10086Handler) http.HandleFunc("/save",saveHandler) log.SetOutput(os.Stdout) err := http.ListenAndServe("127.0.0.1:8088", nil) if err != nil { log.Fatal("ListenAndServe:", err) } }
g10086/g10086.go 模块代码如下
package g10086 import ( "io" "net/http" "strings" "strconv" "encoding/json" "time" ) //全局计数器信息 var G_status map[string] string // type Dstate struct { id string status string Info map[string] string } //更新计数状态,如果计数器A的数字总和超过10,则输出完毕,删除此计数器 func updateStatus (key string, down Dstate) int { total := 0 for _,v := range down.Info { n, err := strconv.Atoi(v) if err != nil { return -1 } total += n if total > 10 { down.status = "Done" break } } if (down.status == "Done") { if _, ok := G_status[key]; ok { delete(G_status,key) } return 1 } else { downinfo, err := json.Marshal(down) if err == nil { G_status[key] = string(downinfo) } return 0 } } func G10086Handler (w http.ResponseWriter, r *http.Request) { key, val := r.PostFormValue("key"), r.PostFormValue("value") if key == "" || val == "" { io.WriteString(w,"no para") return } //查询之前有无对应key的计数器,如果有,则添加记录,如果没有,新建记录 var cur_down Dstate if v, ok := G_status[key]; ok { dec := json.NewDecoder(strings.NewReader(v)) if err := dec.Decode(&cur_down); err != nil { return } cur_down.Info[strconv.Itoa(int(time.Now().Unix()))] = val } else { new_status := map[string] string{strconv.Itoa(int(time.Now().Unix())):val} cur_down = Dstate{id:key, status:"Start", Info:new_status} } res := updateStatus(key, cur_down) switch res { case 1: io.WriteString(w, "Done" + key) case 0: io.WriteString(w, "Continue " + key) default: io.WriteString(w, "Unknown") } }
client端代码如下:
package main import ( "net/http" "net/url" "log" "os" ) func main () { if len(os.Args) < 3 { log.Fatal("para error") } key, val := os.Args[1], os.Args[2] resp, err := http.PostForm("http://127.0.0.1:8088/g10086", url.Values{"key": {key}, "value": {val}}) if err != nil { log.Fatal("Post error : ", err) } if resp.StatusCode == 200 { resp.Write(os.Stdout) } } //使用示例 //go run client.go countA 3 //go run client.go countB 4
静态文件需要添加如下代码,创建template目录,将静态资源放在目录中
http.Handle("/template/", http.StripPrefix("/template/", http.FileServer(http.Dir("./template"))))
同样的静态资源小文件放在nginx和go的性能测试如下:Request Per Second(nginx为7652)(go为5321)
定时器使用如下:
import "time" func timer () { for { timer := time.NewTicker(5 * time.Second) for { select { case <- timer.C: fmt.Print("timer called\n") } } } }
JSON操作
package main import ( "encoding/json" "fmt" "io" "log" "strings" ) func main() { const jsonStream = ` {"Name": "Ed", "Text": "Knock knock."} {"Name": "Sam", "Text": "Who's there?"} {"Name": "Ed", "Text": "Go fmt."} {"Name": "Sam", "Text": "Go fmt who?"} {"Name": "Ed", "Text": "Go fmt yourself!"} ` type Message struct { Name, Text string } //json decode dec := json.NewDecoder(strings.NewReader(jsonStream)) var m Message for { if err := dec.Decode(&m); err == io.EOF { break } else if err != nil { log.Fatal(err) } fmt.Printf("%s: %s\n", m.Name, m.Text) } //json encode dataStream, err := json.Marshal(m) if err != nil { log.Fatal(err) } fmt.Print(string(dataStream)) }
相关推荐
在7进制计数器中,通常只有一个输入——“时钟”(CLK),当时钟脉冲到来时,计数器会从当前状态转换到下一个状态。输出则是当前状态的编码值。 接下来,我们需要创建状态转换表,它定义了在给定输入下,每个状态...
在本主题中,我们关注的是一个特殊类型的计数器——60进制计数器,这种计数器在特定的计算或通信应用中可能会被用到,例如在基于六十进制(如古代巴比伦系统)的时间或角度表示中。60进制计数器不同于常见的二进制、...
【数电实验7——计数器】报告详细解析 本次实验是关于数字电子技术的实践,主要关注计数器的设计与应用。计数器在数字系统中起着至关重要的作用,能够实现对输入脉冲的计数,广泛应用于时序逻辑电路中。实验的核心...
用集成计数器实现任意进制计数器——六进制.ms13
在这个项目中,我们关注的是一个特殊的计数器设计,它可以计数从0到999999,即百万计数器。这个设计不仅考验了单片机的处理能力和存储资源,还涉及到实时系统和数字电路的知识。 首先,让我们了解单片机的基本概念...
在本项目中,“VHDL语言实现的计数器”指的是利用VHDL编写代码,实现一个在FPGA(Field-Programmable Gate Array)开发板上工作的计数器,该计数器能够进行十进制计数,并将结果显示在7段数码管上。这里涉及到的知识...
"时序逻辑电路——60进制同步计数器的实现" 时序逻辑电路是数字电路的核心组件之一,它可以实现各种数字逻辑操作和数据处理。 本文将介绍时序逻辑电路在实现60进制同步计数器中的应用。 一、时序逻辑电路简介 ...
FPGA高速接口设计之SpaceWire——发送模块 FPGA开发是一个复杂的设计,涉及到发送模块的概述、发送模块的功能、发送状态机和流控机制等方面。该设计需要对SpaceWire协议和FPGA高速接口设计有深入的了解和理解。
本文聚焦于使用Verilog设计实现异步双向计数器的技术细节,这一设计不仅体现了Verilog的强大功能,同时也满足了特定应用需求,如接口模块设计中对双向计数、异步置数、清零等功能的需求。 #### 异步双向计数器概述 ...
verilog 0——9999计数器 并能在数码管中显示出来
这个模块通过逻辑门电路或计数逻辑实现,确保正确的时序信号被传递到计数器和RAM。 3. **RAM模块**:该模块负责存储计数器的初始值和暂停时的计数值。它需要包含地址选择逻辑,使得计数器的输出能够根据地址输入...
在这个项目中,我们将探讨如何利用单片机的内部资源,特别是T_CO模块,来设计一个实用的计数器,并通过仿真验证其功能。 首先,我们要理解单片机中的计数器工作原理。计数器通常是由单片机内部的定时器模块驱动,...
总结来说,基于计数器宏功能模块设计的模24方向可控计数器电路是一项综合了数字逻辑设计、硬件描述语言编程和FPGA实现技术的任务。这种计数器在各种应用场景中都有其独特价值,比如在数字信号处理、通信系统和自动化...
实验五的目的是深入理解 JK 触发器的逻辑功能,并掌握如何使用 JK 触发器设计同步和异步计数器。计数器是数字系统中的核心组件,用于跟踪时间序列或数量的变化。JK 触发器是一种双稳态电路,能够实现翻转、置零、...
本课程设计的主题是利用FPGA实现一个十进制计数器,这一主题涵盖了数字电路设计、FPGA基础、硬件描述语言(HDL)以及综合与仿真等多个关键知识点。 十进制计数器是一种能够进行从0到9循环计数的电路,它是数字系统...
这里我们关注的是一个4位宽的十进制计数器,它是用Verilog硬件描述语言实现的。Verilog是一种广泛使用的系统级语言,用于描述数字系统的硬件行为,包括逻辑门、触发器、计数器等各种数字电路。 首先,让我们了解十...