首页 > 代码库 > Go语言小试牛刀---几个简单的例子
Go语言小试牛刀---几个简单的例子
整理资料,发现之前手写的Go语言资料,现在贴过来。
第一个:Channel的使用,创建一个随机数
package main import "fmt"import "runtime"func rand_generator_2() chan int{ out := make(chan int) go func(){ for{ out<-rand.Int() } }() return out}func main(){ rand_service_handler := rand_generator_2() fmt.Printf("%d\n",<-rand_service_handler)}
第二个:实现通过Channel通道求和的例子
package maintype NodeInterface interface { receive(i int) run() int}type Node struct { name string in_degree int in_ch chan int out_ch chan int inode NodeInterface}func NewNode(name string, inode NodeInterface) *Node { //创建一个Node,拥有两个channel return &Node{name, 0, make(chan int), make(chan int), inode}}func (from *Node) ConnectTo(to *Node) { to.in_degree++ go func() { i := <- from.out_ch to.in_ch <- i }()}func (n *Node) Run() { go func() { defer func() { if x := recover(); x != nil { println(n.name, "panic with value ", x) panic(x) } println(n.name, "finished"); }() for n.in_degree > 0 { received := <- n.in_ch n.inode.receive(received) n.in_degree-- } ret := n.inode.run() n.out_ch <- ret }()}type DoubleNode struct { data int}//创建一个新的Nodefunc NewDoubleNode(name string, data int) *Node { return NewNode(name, &DoubleNode{data})}func (n *DoubleNode) receive(i int) {}func (n *DoubleNode) run() int { return n.data * 2}type SumNode struct { data int}func NewSumNode(name string) *Node { return NewNode(name, &SumNode{0})}func (n *SumNode) receive(i int) { n.data += i}func (n *SumNode) run() int { return n.data}func main() { sum := NewSumNode("sum") sum.Run() for _, num := range [5]int{1, 2, 3, 5, 6} { node := NewDoubleNode("double", num) node.ConnectTo(sum) node.Run() } println(<- sum.out_ch)}
第三个例子:Go语言的并发操作,go语言可以适配机器的cpu达到最大并发
package mainimport ( "fmt" "runtime")var workers = runtime.NumCPU()type Result struct { jobname string resultcode int resultinfo string}type Job struct { jobname string results chan<- Result}func main() { // go语言里大多数并发程序的开始处都有这一行代码, 但这行代码最终将会是多余的, // 因为go语言的运行时系统会变得足够聪明以自动适配它所运行的机器 runtime.GOMAXPROCS(runtime.NumCPU()) // 返回当前处理器的数量 fmt.Println(runtime.GOMAXPROCS(0)) // 返回当前机器的逻辑处理器或者核心的数量 fmt.Println(runtime.NumCPU()) // 模拟8个工作任务 jobnames := []string{"gerry", "wcdj", "golang", "C++", "Lua", "perl", "python", "C"} doRequest(jobnames)}func doRequest(jobnames []string) { // 定义需要的channels切片 jobs := make(chan Job, workers) results := make(chan Result, len(jobnames)) done := make(chan struct{}, workers) // --------------------------------------------- /* * 下面是go协程并发处理的一个经典框架 */ // 将需要并发处理的任务添加到jobs的channel中 go addJobs(jobs, jobnames, results) // Executes in its own goroutine // 根据cpu的数量启动对应个数的goroutines从jobs争夺任务进行处理 for i := 0; i < workers; i++ { go doJobs(done, jobs) // Each executes in its own goroutine } // 新创建一个接受结果的routine, 等待所有worker routiines的完成结果, 并将结果通知主routine go awaitCompletion(done, results) // 在主routine输出结果 processResults(results) // ---------------------------------------------}func addJobs(jobs chan<- Job, jobnames []string, results chan<- Result) { for _, jobname := range jobnames { // 在channel中添加任务 jobs <- Job{jobname, results} } close(jobs)}func doJobs(done chan<- struct{}, jobs <-chan Job) { // 在channel中取出任务并计算 for job := range jobs { /* * 定义类型自己的方法来处理业务逻辑, 实现框架和业务分离 */ job.Do() } // 所有任务完成后的结束标志, 一个空结构体切片 done <- struct{}{}}// 方法是作用在自定义类型的值上的一类特殊函数func (job Job) Do() { // 打印当前处理的任务名称 fmt.Printf("... doing work in [%s]\n", job.jobname) // 模拟处理结果 if job.jobname == "golang" { job.results <- Result{job.jobname, 0, "OK"} } else { job.results <- Result{job.jobname, -1, "Error"} }}func awaitCompletion(done <-chan struct{}, results chan Result) { for i := 0; i < workers; i++ { <-done } close(results)}func processResults(results <-chan Result) { for result := range results { fmt.Printf("done: %s,%d,%s\n", result.jobname, result.resultcode, result.resultinfo) }}
第四个:网络编程方面,基于Go实现Ping的操作,比较难,还未看明白
// Copyright 2009 The Go Authors. All rights reserved.// Use of this source code is governed by a BSD-style// license that can be found in the LICENSE file.// taken from http://golang.org/src/pkg/net/ipraw_test.gopackage pingimport ( "bytes" "errors" "net" "os" "time")const ( icmpv4EchoRequest = 8 icmpv4EchoReply = 0 icmpv6EchoRequest = 128 icmpv6EchoReply = 129)type icmpMessage struct { Type int // type Code int // code Checksum int // checksum Body icmpMessageBody // body}type icmpMessageBody interface { Len() int Marshal() ([]byte, error)}// Marshal returns the binary enconding of the ICMP echo request or// reply message m.func (m *icmpMessage) Marshal() ([]byte, error) { b := []byte{byte(m.Type), byte(m.Code), 0, 0} if m.Body != nil && m.Body.Len() != 0 { mb, err := m.Body.Marshal() if err != nil { return nil, err } b = append(b, mb...) } switch m.Type { case icmpv6EchoRequest, icmpv6EchoReply: return b, nil } csumcv := len(b) - 1 // checksum coverage s := uint32(0) for i := 0; i < csumcv; i += 2 { s += uint32(b[i+1])<<8 | uint32(b[i]) } if csumcv&1 == 0 { s += uint32(b[csumcv]) } s = s>>16 + s&0xffff s = s + s>>16 // Place checksum back in header; using ^= avoids the // assumption the checksum bytes are zero. b[2] ^= byte(^s & 0xff) b[3] ^= byte(^s >> 8) return b, nil}// parseICMPMessage parses b as an ICMP message.func parseICMPMessage(b []byte) (*icmpMessage, error) { msglen := len(b) if msglen < 4 { return nil, errors.New("message too short") } m := &icmpMessage{Type: int(b[0]), Code: int(b[1]), Checksum: int(b[2])<<8 | int(b[3])} if msglen > 4 { var err error switch m.Type { case icmpv4EchoRequest, icmpv4EchoReply, icmpv6EchoRequest, icmpv6EchoReply: m.Body, err = parseICMPEcho(b[4:]) if err != nil { return nil, err } } } return m, nil}// imcpEcho represenets an ICMP echo request or reply message body.type icmpEcho struct { ID int // identifier Seq int // sequence number Data []byte // data}func (p *icmpEcho) Len() int { if p == nil { return 0 } return 4 + len(p.Data)}// Marshal returns the binary enconding of the ICMP echo request or// reply message body p.func (p *icmpEcho) Marshal() ([]byte, error) { b := make([]byte, 4+len(p.Data)) b[0], b[1] = byte(p.ID>>8), byte(p.ID&0xff) b[2], b[3] = byte(p.Seq>>8), byte(p.Seq&0xff) copy(b[4:], p.Data) return b, nil}// parseICMPEcho parses b as an ICMP echo request or reply message body.func parseICMPEcho(b []byte) (*icmpEcho, error) { bodylen := len(b) p := &icmpEcho{ID: int(b[0])<<8 | int(b[1]), Seq: int(b[2])<<8 | int(b[3])} if bodylen > 4 { p.Data = http://www.mamicode.com/make([]byte, bodylen-4)"ip4:icmp", address) if err != nil { return } //? c.SetDeadline(time.Now().Add(time.Duration(timeout) * time.Second)) defer c.Close() //>> typ := icmpv4EchoRequest xid, xseq := os.Getpid()&0xffff, 1 wb, err := (&icmpMessage{ Type: typ, Code: 0, Body: &icmpEcho{ ID: xid, Seq: xseq, Data: bytes.Repeat([]byte("Go Go Gadget Ping!!!"), 3), }, }).Marshal() if err != nil { return } if _, err = c.Write(wb); err != nil { return } var m *icmpMessage rb := make([]byte, 20+len(wb)) for { if _, err = c.Read(rb); err != nil { return } rb = ipv4Payload(rb) if m, err = parseICMPMessage(rb); err != nil { return } switch m.Type { case icmpv4EchoRequest, icmpv6EchoRequest: continue } break } return}func ipv4Payload(b []byte) []byte { if len(b) < 20 { return b } hdrlen := int(b[0]&0x0f) << 2 return b[hdrlen:]}
Go语言小试牛刀---几个简单的例子
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。