海运的博客

go redis 连接池

发布时间:August 7, 2015 // 分类:GO // No Comments

package main
import (
  "github.com/garyburd/redigo/redis"
  "fmt"
)
var pool = newPool()
func newPool() *redis.Pool {
  return &redis.Pool{
    MaxIdle: 80,
    MaxActive: 12000, // max number of connections
    Dial: func() (redis.Conn, error) {
      c, err := redis.Dial("tcp", "localhost:6379")
      if err != nil {
        panic(err.Error())
      }
      return c, err
    },
  } 
 
}
func main() {
  c := pool.Get()
  defer c.Close()
  que, err := redis.String(c.Do("LPOP", "test"))
  fmt.Println(que)
  if err != nil {
    fmt.Println("队列空")
  }
}

http://stackoverflow.com/questions/24387350/re-using-redigo-connection-instead-of-recreating-it-every-time
http://blog.csdn.net/stevefang/article/details/40474827

GO语言中的接口interface

发布时间:January 13, 2015 // 分类:GO // No Comments

interface类型定义了一组方法,如果某个对象实现了某个接口的所有方法,则此对象就实现了此接口。
如果我们定义了一个interface的变量,那么这个变量里面可以存实现这个interface的任意类型的对象。

package main

import (
        "fmt"
)

//定义一个USB接口
type USB interface {
        say()
}

//定义SD类型
type Sd struct {
        name string
}

//SD类型内定义say方法,即实现了USB接口
func (s Sd) say() {
        fmt.Println("这是", s.name)
}

//定义MP3类型
type Mp3 struct {
        name string
}

//同样MP3类型内定义say方法,即实现了USB接口
func (m Mp3) say() {
        fmt.Println("这是", m.name)
}

func who(u USB) {
u.say()
}
func main() {
    //新建USB类型变量
        var i USB
    //可存放MP3类型数据
        i = Mp3{"mp3"}
    //调用MP3类型方法
        i.say()
    //也可存放SD类型数据
        i = Sd{"SD"}
    //调用SD类型方法
        i.say()

}

空接口interface{},由于interface{}未实现任何方法,代表任意类型都实现了interface{},即interface{}可存放任意类型的数据。
有一点要注意,任意类型可赋值给interface{},interface{}类型数据不能直接赋值给任何其它类型,要做类型转换,类似于C中的void*

package main

import (
    "fmt"
    "reflect"
)

func main() {
    var general interface{}
    general = 2
    v := reflect.ValueOf(general)
    fmt.Println("type:", v.Type())
    switch general.(type) {
    case int:
        fmt.Println(general)
    case string:
        fmt.Println(general)
    }

}

GO标准库中interface接口应用,在标准库io包中定义了Writer接口,所有实现了Write方法的类型,我们都说它实现了io.Writer接口。

type Writer interface {
    Write(p []byte) (n int, err error)
}

我们在使用fmt包的时候是使用Println/Printf/Print方法。其实,在fmt包中还有Fprint序列方法,而且,Print序列方法内部调用的是Fprint序列方法。以Fprintln为例看看方法的定义:

func Fprintln(w io.Writer, a ...interface{}) (n int, err error)

方法的第一个参数是io.Writer,也就是说,任何实现了io.Writer接口的类型实例都可以传递进来;我们再看看Println方法内部实现:

func Println(a ...interface{}) (n int, err error) {
    return Fprintln(os.Stdout, a...)
}

我们不妨追溯一下os.Stdout,也就是标准输出。

Stdout = NewFile(uintptr(syscall.Stdout), "/dev/stdout")

从这里可以看出,os.File也实现了io.Writer,那么,如果第一个参数传递的是一个普通文件,内容便会被输出到该文件。
如果第一个参数传递的是bytes.Buffer,那么,内容便输出到了buffer中。
在写Web程序时,比如:

func Index(rw http.ResponseWriter, req *http.Request) {
    fmt.Fprintln(rw, "Hello, World")
}

这样便把Hello World输出给了客户端。
http://blog.studygolang.com/2013/02/%e4%bb%a5io-writer%e4%b8%ba%e4%be%8b%e7%9c%8bgo%e4%b8%ad%e7%9a%84interface/
https://github.com/astaxie/build-web-application-with-golang/blob/master/zh/02.6.md

GO生成随机数字/英文字符串

发布时间:January 8, 2015 // 分类:GO // No Comments

package main

import (
        //"fmt"
        "math/rand"
)

func randSeq(n int) string {
        //letters := []rune("abcdefghijklmnopqrstuvwxyz")
        letters := []rune("0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz")
        b := make([]rune, n)
        for i := range b {
                b[i] = letters[rand.Intn(len(letters))]
        }
        return string(b)
}

func main() {
        for i := 1; i < 1000000; i++ {
                //fmt.Println(randSeq(5))
                randSeq(5)
        }
}

http://stackoverflow.com/questions/22892120/how-to-generate-a-random-string-of-a-fixed-length-in-golang
http://stackoverflow.com/questions/12771930/what-is-the-fastest-way-to-generate-a-long-random-string-in-go

GO HTTP client客户端使用

发布时间:January 6, 2015 // 分类:GO // No Comments

简单:

package main

import (
    "fmt"
    "io/ioutil"
    "net/http"
    "strings"
)

func main() {
    res, err := http.Get("https://www.haiyun.me/")
    if err != nil {
        return
    }
        //执行close之前一定要判断错误,如没有body会崩溃
    defer res.Body.Close()
        //重用连接一定要执行上和下两步
    body, _ := ioutil.ReadAll(res.Body)
    fmt.Println(string(body))
        fmt.Println(res.Status)
    for k, v := range res.Header {
        fmt.Println(k, strings.Join(v, ""))
    }

}

自定义client,连接读写超时及自定义head:

package main

import (
        "fmt"
        "io/ioutil"
        "net/http"
        "strings"
        "time"
)

var timeout = time.Duration(20 * time.Second)

func dialTimeout(network, addr string) (net.Conn, error) {
        return net.DialTimeout(network, addr, timeout)
}

func main() {
        tr := &http.Transport{
                //使用带超时的连接函数
                Dial: dialTimeout,
                //建立连接后读超时
                ResponseHeaderTimeout: time.Second * 2,
                //直接通过ip访问时设置sni
                TLSClientConfig: &tls.Config{
                     ServerName: "www.haiyun.me",
                },
        }
        client := &http.Client{
                Transport: tr,
                //总超时,包含连接读写
                Timeout: timeout,
        }
        req, _ := http.NewRequest("GET", "https://www.haiyun.me", nil)
        req.Header.Set("Connection", "keep-alive")
        req.Header.Set("Host", "www.haiyun.me")
        res, err := client.Do(req)
        if err != nil {
                return
        }
        defer res.Body.Close()
        body, _ := ioutil.ReadAll(res.Body)
        fmt.Println(string(body))
        for k, v := range res.Header {
                fmt.Println(k, strings.Join(v, ""))
        }

}

使用代理及指定出口IP:

        //使用HTTP PROXY
        proxyUrl, err := url.Parse("http://host:port")
        tr := &http.Transport{
                Proxy: http.ProxyURL(proxyUrl),
        }
        //指定出口IP
        ief, err := net.InterfaceByName("eth0")
        addrs, err := ief.Addrs()
        addr := &net.TCPAddr{
                IP: addrs[0].(*net.IPNet).IP,
        }
        dia := net.Dialer{LocalAddr: addr}
        tr := &http.Transport{
                Dial: dia.Dial,
        }

使用socks5代理:https://github.com/hailiang/socks
http://golang.org/pkg/net/http/#Client
http://golang.org/pkg/net/http/#Transport
http://golang.org/pkg/net/#Dialer

GO协程同步及限制协程数

发布时间:January 3, 2015 // 分类:GO // No Comments

使用同步锁同步:

package main

import "fmt"
import "time"
import "sync"

func main() {
        var wg sync.WaitGroup
        //生成带缓存的chan
        var limit = make(chan struct{}, 10)

        for i := 0; i < 100; i++ {
                //写入chan,直到缓存写满阻塞,即限制协程数
                limit <- struct{}{}
                //同步计数加1
                wg.Add(1)
                go func(i int) {
                        time.Sleep(1000 * time.Millisecond)
                         fmt.Println(i)
                        //协程内任务完成读取chan,主协程可继续写入chan
                        <-limit
                        //同步计数减1
                        defer wg.Done()
                }(i)
        }
        //同步阻塞直到计数为0,即所有协程完成
        wg.Wait()
}

使用channel同步:

package main

import "fmt"
import "time"

var sync chan int;
func foo(i int) {
        fmt.Println(i)
        time.Sleep(time.Second) 
        sync <- 0 
}

func main() {
        count := 100
        sync = make(chan int, count) 

        for i := 0; i < count; i++ {
                go foo(i)
        }

        //等待所有协程完成
        for i := 0; i < count; i++ {
                <-sync
        }
}
分类
最新文章
最近回复
  • opnfense: 谢谢博主!!!解决问题了!!!我之前一直以为内置的odhcp6就是唯一管理ipv6的方式
  • liyk: 这个方法获取的IPv6大概20分钟之后就会失效,默认路由先消失,然后Global IPV6再消失
  • 海运: 不好意思,没有。
  • zongboa: 您好,請問一下有immortalwrt設定guest Wi-Fi的GUI教學嗎?感謝您。
  • 海运: 恩山有很多。
  • swsend: 大佬可以分享一下固件吗,谢谢。
  • Jimmy: 方法一 nghtp3步骤需要改成如下才能编译成功: git clone https://git...
  • 海运: 地址格式和udpxy一样,udpxy和msd_lite能用这个就能用。
  • 1: 怎么用 编译后的程序在家里路由器内任意一台设备上运行就可以吗?比如笔记本电脑 m参数是笔记本的...
  • 孤狼: ups_status_set: seems that UPS [BK650M2-CH] is ...