首页 > 代码库 > 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语言小试牛刀---几个简单的例子