第1章 初识Go语言

  1.1 语言简史

  1.2 语言特性

    1.2.1 自动垃圾回收

    1.2.2 更丰富的内置类型

    1.2.3 函数多返回值

    1.2.4 错误处理

    1.2.5 匿名函数和闭包

    1.2.6 类型和接口

    1.2.7 并发编程

package main

import "fmt"

func sum(values []int,resultChan chan int) {
    sum :=
    for _,value := range values {
        sum += value
    }
    resultChan <- sum
}

func main() {
    values := [],,,,,,,,,}

    resultChan := make(chan )
    go sum(values[:len(values)/],resultChan)
    go sum(values[len(values)/:],resultChan)

    sum1,sum2 := <-resultChan,<-resultChan

    fmt.Println("Result:",sum1,sum2,sum1+sum2)
}

paracalc

    1.2.8 反射

package main

import (
    "fmt"
    "reflect"
)

type Bird struct {
    Name string
    LifeExpectance int
}

func (b *Bird) Fly() {
    fmt.Println("I am flying...")
}

func main() {
    sparrow := &Bird{}
    s := reflect.ValueOf(sparrow).Elem()
    typeOfT := s.Type()
    ; i < s.NumField(); i++ {
        f := s.Field(i)
        fmt.Printf("%d: %s %s = %v\n",i,typeOfT.Field(i).Name,f.Type(),f.Interface())
    }
}

reflect

    1.2.9 语言交互性

package main

/*
#include <stdio.h>
*/
import "C"
import "unsafe"

func main() {
    cstr := C.CString("Hello,World")
    C.puts(cstr)
    C.free(unsafe.Pointer(cstr))
}

cprint

  1.3 第一个Go程序

package main

import "fmt"

func main() {
    fmt.Println("Hello,World")
}

Hello World

    1.3.1 代码解读

    1.3.2 编译环境准备

$go version

    1.3.3 编译程序

  1.4 开发工具选择

  1.5 工程管理

package main

import "os"
import "fmt"
import "simplemath"
import "strconv"

var Usage = func() {
    fmt.Println("USAGE: calc command [arguments] ...")
    fmt.Println("\nThe commands are:\n\tadd\tAddition of two values.\n\tsqrt\tSquare
        root of a non-negative value.")
}

func main() {
    args := os.Args
     {
        Usage()
        return
    }

    ] {
        case "add":
             {
                fmt.Println("USAGE: cacl add <integer1><integer2>")
                return
            }
            v1,err1 := strconv.Atoi(args[])
            v2,err2 := strconv.Atoi(args[])
            if err1 != nil || err2 != nil {
                fmt.Println("USAGE: calc add<integer1><integer2>")
                return
            }
            ret := simplemath.Add(v1,v2)
            fmt.Println("Result: ",ret)
        case "sqrt":
             {
                fmt.Println("USAGE: calc sqrt <integer>")
                return
            }
            v,err := strconv.Atoi(args[])
            if err != nil {
                fmt.Println("USAGE: calc sqrt <integer>")
                return
            }
            ret := simplemath.Sqrt(v)
            fmt.Println("Result: ",ret)
        default:
            Usage()
    }
}

calcl

package simplemath

func Add(a int,b int) int {
    return a + b
}

add

package simplemath

import "testing"

func TestAdd1(t *testing.T) {
    r := Add(,)
     {
        t.Errorf("Add(1,2) failed.Got %d,expected 3.",r)
    }
}

add_test

package simplemath

import "math"

func Sqrt(i int) int {
    v := math.Sqrt(float64(i))
    return int(v)
}

sqrt

package simplemath

import "testing"

func TestSqrt1(t *testing.T) {
    v := Sqrt()
     {
        t.Errorf("Sqrt(16) failed.Got %v,expected 4.",v)
    }
}

sqrt_test

  1.6 问题追踪和调试

    1.6.1 打印日志

    1.6.2 GDB调试

  1.7 如何寻求帮助

    1.7.1 邮件列表

    1.7.2 网站资源

  1.8 小结

第2章 顺序编程

  2.1 变量

    2.1.1 变量声明

var v1 int
var v2 string
]int
var v4 []int
var v5 struct {
    f int
}
var v6 *int
var v7 map[string]int
var v8 func(a int) int

var (
    v1 int
    v2 string
)

varTest1

    2.1.2 变量初始化


v3 := 

varTest2

    2.1.3 变量赋值

var v10 int
v10 = 

i,j = j,i

varTest3

    2.1.4 匿名变量

func GetName() (firstName,lastName,nickName string) {
    return "May","Chan","Chibi Maruko"
}
_,_,nickName := GetName()

varTest4

  2.2 常量

    2.2.1 字面常量

    2.2.2 常量定义

const Pi float64 = 3.14159265358979323846
const zero = 0.0
const (
    size int64 =
    eof = -
)
,
,,"foo"
 << 

varTest5

    2.2.3 预定义常量

const (
    c0 = iota
    c1 = iota
    c2 = iota
)

const (
    a =  << iota
    b =  << iota
    c =  << iota
)

const (
    u = iota *
    v float64 = iota *
    w = iota *
)

const x = iota
const y = iota

const (
    c0 = iota
    c1
    c2
)

const (
    a =  << iota
    b
    c
)

varTest6

    2.2.4 枚举

const (
    Sunday = iota
    Monday
    Tuesday
    Wednesday
    Thursday
    Friday
    Saturday
    numberOfDays
)

varTest7

  2.3 类型

布尔类型:bool
整型:int8,byte,int16,int,uint,uintptr等
浮点类型:float32,float64
复数类型:complex64,complex128
字符串:string
字符类型:rune
错误类型:error
指针(pointer)
数组(array)
切片(slice)
字典(map)
通道(chan)
结构体(struct)
接口(interface)

类型

    2.3.1 布尔类型

    2.3.2 整型

    2.3.3 浮点型

import "math"

// p为用户定义的比较精度,比如0.00001
func IsEqual(f1,f2,p float64) bool {
    return math.Fdim(f1,f2) < p
}

    2.3.4 复数类型

    2.3.5 字符串

package main

import "fmt"

func main() {
    str := "Hello, 世界"
    n := len(str)
    ; i < n; i++ {
        ch := str[i]
        fmt.Println(i,ch)
    }

    for i,ch := range str {
        fmt.Println(i,ch)
    }
}

    2.3.6 字符类型

    2.3.7 数组

package main

import "fmt"

func Modify(array []int) {
    array[] =
    fmt.Println("In Modify(),array values:",array)
}

func main() {
    array := [],,,,}

    Modify(array)

    fmt.Println("In main(),array values:",array)
}

    2.3.8 数组切片

package main

import "fmt"

func main() {
    ]],,,,,,,,,}
    ]

    fmt.Println("Elements of myArray: ")
    for _,v := range myArray {
        fmt.Print(v," ")
    }
    fmt.Println("\nElements of mySlice: ")
    for _,v := range mySlice {
        fmt.Print(v," ")
    }
    fmt.Println()

    mySlice1 := make([])
    mySlice2 := make([],)
    mySlice3 := [],,,,}
}

slice1

package main

import "fmt"

func main() {
    mySlice := make([],)
    fmt.Println("len(mySlice):",len(mySlice))
    fmt.Println("cap(mySlice):",cap(mySlice))

    mySlice = append(mySlice,,,)

    mySlice2 := [],,}
    mySlice = append(mySLice,mySlice2...)
}

slice2

    2.3.9 map

package main

import "fmt"

type PersonInfo struct {
    ID string
    Name string
    Address string
}

func main() {
    var personDB map[string]PersonInfo
    personDB = make(map[string]PersonInfo)
    personDB[","Tom","Room 203,..."}
    personDB[","Jack","Room 101,..."}

    person,ok := personDB["]

    if ok {
        fmt.Println("Found person",person.Name,"with ID 1234.")
    } else {
        fmt.Println("Did not find person with ID 1234.")
    }
}

map1

  2.4 流程控制

    2.4.1 条件语句

    2.4.2 选择语句

switch i {
    :
        fmt.Printf(")
    :
        fmt.Printf(")
    :
        fallthrough
    :
        fmt.Printf(")
    ,,:
        fmt.Printf("4,5,6"")
    default:
        fmt.Printf("Default")
}

switch {
     <= Num && Num <= :
        fmt.Printf("0-3")
     <= Num && Num <= :
        fmt.Printf("4-6")
     <= NUM && Num <= :
        fmt.Printf("7-9")
}

switch

    2.4.3 循环语句

sum :=
; i < ; i++ {
    sum += i
}

sum :=
for {
    sum ++
     {
        break
    }
}

a := [],,,,,}
, len(a) - ; i < j;i,j = i + , j -  {
    a[i],a[j] = a[j],a[i]
}

; j < ; j++ {
    ; i < ; i++ {
         {
            break JLoop
        }
        fmt.Println(i)
    }
}
JLoop:

for

    2.4.4 跳转语句

func myfunc() {
    i :=
    HERE:
        fmt.Println(i)
    i++
     {
        goto HERE
    }
}

goto

  2.5 函数

    2.5.1 函数定义

    2.5.2 函数调用

    2.5.3 不定参数

package main

import "fmt"

func MyPrintf(args ...interface{}) {
    for _,arg := range args {
        switch arg.(type) {
            case int:
                fmt.Println(arg,"is an int value.")
            case string:
                fmt.Println(arg,"is a string value.")
            case int64:
                fmt.Println(arg,"is an int64 value.")
            default:
                fmt.Println(arg,"is an unknown type.")
        }
    }
}

func main() {

    var v3 string = "hello"
    var v4 float32 = 1.234

    MyPrintf(v1,v2,v3,v4)
}

varg1

    2.5.4 多返回值

    2.5.5 匿名函数与闭包

package main

import "fmt"

func main() {

    a := func()(func()) {

        return func() {
            fmt.Printf("i,j:%d,%d\n",i,j)
        }
    }()

    a()

    j *= 

    a()
}

closure

  2.6 错误处理

    2.6.1 error接口

    2.6.2 defer

    2.6.3 panic()和recover()

  2.7 完整示例

    2.7.1 程序结构

    2.7.2 主程序

    2.7.3 算法实现

    2.7.4 主程序

    2.7.5 构建与执行

  2.8 小结

第3章 面向对象编程

  3.1 类型系统

    3.1.1 为类型添加方法

package main

import "fmt"

type Integer int

func (a Integer) Less(b Integer) bool {
    return a < b
}

func (a *Integer) Add(b Integer) {
    *a += b
}

func (a Integer) Add1(b Integer) {
    a += b
}

func main() {

    ) {
        fmt.Println(a,"Less 2")
    }

    a.Add()
    fmt.Println("a = ",a)

    a.Add1()
    fmt.Println("a = ",a)
}

    3.1.2 值语义和引用语义

    3.1.3 结构体

  3.2 初始化

  3.3 匿名组合

  3.4 可见性

  3.5 接口

    3.5.1 其他语言的接口

    3.5.2 非侵入式接口

type File struct {

}

func (f *File) Read(buf []byte) (n int,err error)
func (f *File) Write(buf []byte) (n int,err error)
func (f *File) Seek(off int64,whence int) (pos int64,err error)
func (f *File) Close() error

type IFile interface {
    Read(buf []byte) (n int,err error)
    Write(buf []byte) (n int,err error)
    Seek(off int64,whence int) (pos int64,err error)
    Close() error
}

type IReader interface {
    Read(buf []byte) (n int,err error)
}

type IWriter interface {
    Write(buf []byte) (n int,err error)
}

type ICloser interface {
    Close() error
}

var file1 IFile = new(File)
var file2 IReader = new(File)
var file3 IWriter = new(File)
var file4 ICloser = new(File)

    3.5.3 接口赋值

package one

type ReadWriter interface {
    Read(buf []byte) (n int,err error)
    Write(buf []byte) (n int,err error)
}

package two

type IStream interface {
    Write(buf []byte) (n int,err error)
    Read(buf []byte) (n int,err error)
}

var file1 two.IStream = new (File)
var file2 one.ReadWriter = file1
var file3 two.IStream = file2

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

var file1 two.IStream = new(File)
var file4 Writer = file1

var file1 Writer = new(File)
var file5 two.IStream = file1 // 编译不能通过

    3.5.4 接口查询

var file1 Writer = ...
if file5,ok := file1.(two.IStream); ok {
    ...
}

var file1 Writer = ...
if file6,ok := file1.(*File); ok {
    ...
}

    3.5.5 类型查询

    3.5.6 接口组合

    3.5.7 Any类型

  3.6 完整示例

    3.6.1 音乐库

    3.6.2 音乐播放

    3.6.3 主程序

    3.6.4 构建运行

    3.6.5 遗留问题

  3.7 小结

第4章 并发编程

  4.1 并发基础

  4.2 协程

  4.3 goroutine

package main

import "fmt"

func Add(x,y int) {
    z := x + y
    fmt.Println(z)
}

func main() {
    ; i <  ; i++ {
        go Add(i,i)
    }
}

add

  4.4 并发通信

package main

import "fmt"
import "sync"
import "runtime"

func Count(lock *sync.Mutex) {
    lock.Lock()
    counter++
    fmt.Println(counter)
    lock.Unlock()
}

func main() {
    lock := &sync.Mutex{}

    ; i < ; i++ {
        go Count(lock)
    }

    for {
        lock.Lock()

        c := counter

        lock.Unlock()

        runtime.Gosched()

         {
            break
        }
    }
}

thread

  4.5 channel

package main

import "fmt"

func Count(ch chan int) {
    ch <-
    fmt.Println("Counting")
}

func main() {
    chs := make([]chan )
    ;i < ; i++ {
        chs[i] = make(chan int)
        go Count(chs[i])
    }

    for _,ch := range(chs) {
        <-ch
    }
}

channel

    4.5.1 基本语法

var chanName chan ElementType

var ch chan int

var m map[string]chan bool

ch := make(chan int)

ch <- value // 写入channel
value := <-ch    // 读取channel

    4.5.2 select

select {
    case <-chan1:
        // 如果chan1成功读取数据,则进行该case处理语句
    :
        // 如果成功向chan2写入数据,则进行该case处理语句
    default:
        // 如果上面都没有成功,则进入default处理流程
}

ch := make(chan )

for {
    select {
        :
        :
    }
    i := <-ch
    fmt.Println("Value received:",i)
}

    4.5.3 缓冲机制

    4.5.4 超时机制

// 首先,我们实现并执行一个匿名的超时等待函数
timeout := make(chan )

go func() {
    time.Sleep(1e9)    // 等待一秒钟
    timeout <- true
}()

// 然后我们把timeout这个channel利用起来
select {
    case <-ch:
        // 从ch中读取到数据
    case <-timeout:
        // 一致没有从ch中读取到数据,但从timeout中读取到了数据
}

    4.5.5 channel的传递

type PipeData struct {
    value int
    handler func(int) int
    next chan int
}

func handle(queue chan *PipeData) {
    for data := range queue {
        data.next <- data.handler(data.value)
    }
}

    4.5.6 单向channel

var ch1 chan int
var ch2 chan<- float64
var ch3 <-chan int

ch4 := make(chan int)
ch5 := <-chan int(ch4)
ch6 := chan<- int(ch4)

    4.5.7 关闭channel

close(ch)
x,ok := <-ch

  4.6 多核并行化

type Vector []float64

func(v Vector) DoSome(i,n int,u Vector,c chan int) {
    for ;i < n;i++ {
        v[i] += u.Op(v[i])
    }
    c <-
}

func (v Vector) DoAll(u Vecotr) {
    c := make(chan int,NCPU)

    ;i < NCPU;i++ {
        go v.DoSome(i*len(v)/NCPU,(i+)*len(v)/NCPU,u,c)
    }

    ;i < NCPU;i++ {
        <-c
    }
}

runtime.GOMAXPROCS()

  4.7 出让时间片

  4.8 同步

    4.8.1 同步锁

    4.8.2 全局唯一性操作

var a string
var once sync.Once

func setup() {
    a = "hello,world"
}

func dropint() {
    once.Do(setup)
    print(a)
}

func twoprint() {
    go doprint()
    go dropinit()
}

  4.9 完整示例

    4.9.1 简单IPC框架

    4.9.2 中央服务器

    4.9.3 主程序

    4.9.4 运行小程序

  4.10 小结

第5章 网络编程

  5.1 Socket编程

    5.1.1 Dial()函数

    5.1.2 ICMP示例程序

    5.1.3 TCP示例程序

package main

import (
    "net"
    "os"
    "bytes"
    "fmt"
    "io"
)

func main() {
     {
        fmt.Fprintf(os.Stderr,])
        os.Exit()
    }
    service := os.Args[]

    conn,err := net.Dial("tcp",service)
    checkError(err)

    _,err = conn.Write([]byte("HEAD / HTTP/1.0\r\n\r\n"))
    checkError(err)

    result,err := readFully(conn)
    checkError(err)

    fmt.Println(string(result))
    os.Exit()
}

func checkError(err error) {
    if err != nil {
        fmt.Fprintf(os.Stderr,"Fatal error: %s",err.Error())
        os.Exit()
    }
}

func readFully(conn net.Conn) ([]byte,error) {
    defer conn.Close()

    result := bytes.NewBuffer(nil)
    ]byte
    for {
        n,err := conn.Read(buf[:])
        result.Write(buf[:n])
        if err != nil {
            if err == io.EOF {
                break
            }
            return nil,err
        }
    }
    return result.Bytes(),nil
}

simplehttp

    5.1.4 更丰富的网络通信

//func DialTCP(net string,laddr,raddr *TCPAddr) (c *TCPConn,err error)
//func DialUDP(net string,laddr,raddr *UDPAddr) (c *UDPConn,err error)
//func DialIP(netProto string,laddr,raddr *IPAddr) (*IPConn,error)
//func DialUnix(net string,laddr,raddr *UnixAddr) (c *UnixConn,err error)

package main

import (
    "net"
    "os"
    "fmt"
    "io/ioutil"
)

func main() {
     {
        fmt.Fprintf(os.Stderr,])
        os.Exit()
    }
    service := os.Args[]

    tcpAddr,err := net.ResolveTCPAddr("tcp4",service)
    checkError(err)

    conn,err := net.DialTCP("tcp",nil,tcpAddr)
    checkError(err)

    _,err = conn.Write([]byte("HEAD / HTTP1.0\r\n\r\n"))
    checkError(err)

    result,err := ioutil.ReadAll(conn)
    checkError(err)

    fmt.Println(string(result))

    os.Exit()
}

func checkError(err error) {
    if err != nil {
        fmt.Fprintf(os.Stderr,"Fatal error: %s",err.Error())
        os.Exit()
    }
}

simplehttp2

  5.2 HTTP编程

    5.2.1 HTTP客户端

package main

import (
    "net/http"
)

type OurCustomTransport struct {
    Transport http.RoundTripper
}

func (t *OurCustomTransport) transport() http.RoundTripper {
    if t.Transport != nil {
        return t.Transport
    }
    return http.DefaultTransport
}

func (t *OurCustomTransport) RoundTrip(req *http.Request) (*http.Response,error) {
    // 处理一些事情
    // 发起HTTP请求
    // 添加一些域到req.Header中
    return t.transport().RoundTrip(req)
}

func (t *OurCustomTransport) Client() *http.Client {
    return &http.Client{Transport:t}
}

func main() {
    t := &OurCustomTransport {
        //...
    }

    c := t.Client()
    resp,err := c.Get("http://example.com")
    // ...
}

customtrans

    5.2.2 HTTP服务端

  5.3 RPC编程

    5.3.1 Go语言中的RPC支持与处理

    5.3.2 Gob简介

    5.3.3 设计优雅的RPC接口

  5.4 JSON处理

    5.4.1 编码为JSON格式

func Marshal(v interface{}) ([]byte,error)

type Book struct {
    Title string
    Authors []string
    Publisher string
    IsPublished bool
    Price float
}

gobook := Book {
    "Go语言编程",
    ["XuShiwei","HughLv"],
    "ituring.com.cn",
    true,
    9.99
}

b,err := json.Marshal(gobook)

b == []byte('{
    "Title":"Go语言编程",
    "Authors":["XuShiwei","HughLv"],
    "Publisher":"ituring.com.cn",
    "IsPublished":true,
    "Price":9.99
    }')

    5.4.2 解码JSON数据

func Unmarshal(data []byte,v interface{}) error

var book Book

err := json.Unmarshal(b,&book)

book := Book{
    "Go语言编程“,
    ["XuShiwei","HughLv"],
    "ituring.com.cn",
    true,
    9.99
}

b := []byte('{"Title":"Go语言编程","Sales":100000}')
var gobook Book
err := json.Unmarshal(b,&gobook)

    5.4.3 解码未知结构的JSON数据

b := []byte('{
    "Title":"Go语言编程",
    "Authors":["XuShiwei",HughLv"],
    "Publisher":"ituring.com.cn",
    "IsPublished":true,
    "Price":9.99,

    }')

var r interface{}
err := json.Unmarshal(b,&r)

map[string]interface{}{
    "Title":"Go语言编程",
    "Authors":["XuShiwei",HughLv"],
    "Publisher":"ituring.com.cn",
    "IsPublished":true,
    "Price":9.99,

}

gobook,ok := r.(map[string]interface{})

if ok {
    for k,v := range gobook {
        switch v2 := v.(type) {
            case string:
                fmt.Println(k,"is string",v2)
            case int:
                fmt.Println(k,"is int",v2)
            case bool:
                fmt.Println(k,"is bool",v2)
            case []interface{}:
                fmt.Println(k,"is an array:")
                for i,iv := range v2 {
                    fmt.Println(i,iv)
                }
            default:
                fmt.Println(k,"is another type not handle yet")
        }
    }
}

    5.4.4 JSON的流式读写

package main

import (
    "encoding/json"
    "log"
    "os"
)

func main() {
    dec := json.NewDecoder(os.Stdin)
    enc := json.NewEncoder(os.Stdout)

    for {
        var v map[string]interface{}
        if err := dec.Decode(&v); err != nil {
            log.Println(err)
        }
        for k := range v {
            if k != "Title" {
                v[k] = nil,false
            }
        }
        if err := enc.Encode(&v); err != nil {
            log.Println(err)
        }
    }
}

jsondemo

  5.5 网站开发

    5.5.1 最简单的网站程序

package main

import (
    "io"
    "log"
    "net/http"
)

func helloHandler(w http.ResponseWriter,r *http.Request) {
    io.WriteString(w,"Hello,world!")
}

func main() {
    http.HandleFunc("/hello",helloHandler)
    err := http.ListenAndServe(":8080",nil)
    if err != nil {
        log.Fatal("ListenAndServ: ",err.Error())
    }
}

hello

    5.5.2 net/http包简介

    5.5.3 开发一个简单的相册网站

  5.6 小结

第6章 安全编程

  6.1 数据加密

  6.2 数字签名

  6.3 数字证书

  6.4 PKI体系

package main

import (
    "fmt"
    "crypto/sha1"
    "crypto/md5"
)

func main() {
    TestString := "Hi,pandaman!"

    Md5Inst := md5.New()
    Md5Inst.Write([]byte(TestString))
    Result := Md5Inst.Sum([]byte(""))
    fmt.Printf("%x\n\n",Result)

    Sha1Inst := sha1.New()
    Sha1Inst.Write([]byte(TestString))
    Result = Sha1Inst.Sum([]byte(""))
    fmt.Printf("%x\n\n",Result)
}

hash1

package main

import (
    "io"
    "fmt"
    "os"
    "crypto/md5"
    "crypto/sha1"
)

func main() {
    TestFile := "123.txt"
    infile,inerr := os.Open(TestFile)

    if inerr == nil {
        md5h := md5.New()
        io.Copy(md5h,infile)
        fmt.Printf("%x %s\n",md5.Sum([]byte("")),TestFile)

        sha1h := sha1.New()
        io.Copy(sha1h,infile)
        fmt.Printf("%x %s\n",sha1h.Sum([]byte("")),TestFile)
    } else {
        fmt.Println(inerr)
        os.Exit()
    }
}

hash2

  6.5 Go语言的哈希函数

  6.6 加密通道

    6.6.1 加密通信流程

    6.6.2 支持HTTPS的Web服务器

package main

import (
    "fmt"
    "net/http"
)

const SERVER_DOMAIN = "localhost"
const RESPONSE_TEMPLATE = "hello"

func rootHandler(w http.ResponseWriter,req *http.Request) {
    w.Header().Set("Content-Type","text/html")
    w.Header().Set("Content-Length",fmt.Sprint(len(RESPONSE_TEMPLATE)))
    w.Write([]byte(RESPONSE_TEMPLATE))
}

func main() {
    http.HandleFunc(fmt.Sprintf("%s:%d/",SERVER_DOMAIN,SERVER_PORT),rootHandler)
    http.ListenAndServeTLS(fmt.Sprintf(":%d",SERVER_PORT),"rui.crt","rui.key",nil)
}

https

package main

import (
    "net"
    "net/http"
    "time"
    "fmt"
    "crypto/x509"
    "crypto/rand"
    "crypto/rsa"
    "crypto/tls"
    "encoding/pem"
    "errors"
    "io/ioutil"
)

const SERVER_DOMAIN = "localhost"
const RESPONSE_TEMPLATE = "hello"

func rootHandler(w http.ResponseWriter,req *http.Request) {
    w.Header().Set("Content-Type","text/html")
    w.Header().Set("Content-Length",fmt.Sprint(len(RESPONSE_TEMPLATE)))
    w.Write([]byte(RESPONSE_TEMPLATE))
}

func YourListenAndServeTLS(addr string,certFile string,keyFile string,handler http.Handler) error {
    config := &tls.Config {
        Rand: rand.Reader,
        Time: time.Now,
        NextProtos: []string{"http/1.1."},
    }

    var err error
    config.Certificates = make([]tls.Certificate,)
    config.Certificates[],err = YourLoadX509KeyPair(certFile,keyFile)
    if err != nil {
        return err
    }

    conn,err := net.Listen("tcp",addr)
    if err != nil {
        return err
    }

    tlsListener := tls.NewListener(conn,config)
    return http.Serve(tlsListener,handler)
}

func YourLoadX509KeyPair(certFile string,keyFile string) (cert tls.Certificate,err error) {
    certPEMBlock,err := ioutil.ReadFile(certFile)
    if err != nil {
        return
    }

    certDERBlock,restPEMBlock := pem.Decode(certPEMBlock)
    if certDERBlock == nil {
        err = errors.New("crypto/tls: failed to parse certificate PEM data")
        return
    }

    certDERBlockChain,_ := pem.Decode(restPEMBlock)
    if certDERBlockChain == nil {
        cert.Certificate = [][]byte{certDERBlock.Bytes}
    } else {
        cert.Certificate = [][]byte{certDERBlock.Bytes,certDERBlockChain.Bytes}
    }

    keyPEMBlock,err := ioutil.ReadFile(keyFile)
    if err != nil {
        return
    }

    keyDERBlock,_ := pem.Decode(keyPEMBlock)
    if keyDERBlock == nil {
        err = errors.New("crypto/tls: failed to parse key PEM data")
        return
    }

    key,err := x509.ParsePKCS1PrivateKey(keyDERBlock.Bytes)
    if err != nil {
        err = errors.New("crypto/tls: failed to parse key")
        return
    }

    cert.PrivateKey = key

    x509Cert,err := x509.ParseCertificate(certDERBlock.Bytes)
    if err != nil {
        return
    }

     {
        err = errors.New("crypto/tls: private key does not match public key")
        return
    }

    return
}

func main() {
    http.HandleFunc(fmt.Sprintf("%s:%d/",SERVER_DOMAIN,SERVER_PORT),rootHandler);
    YourListenAndServeTLS(fmt.Sprintf(":%d",SERVER_PORT),"rui.crt","rui.key",nil)
}

https2

    6.6.3 支持HTTPS的文件服务器

package main

import (
    "net/http"
)

func main() {
    h := http.FileServer(http.Dir("."))
    http.ListenAndServeTLS(":8001","rui.crt","rui.key",h)
}

httpsfile

    6.6.4 基于SSL/TLS的ECHO程序

  6.7 小结

第7章 工程管理

  7.1 Go命令行工具

  7.2 代码风格

    7.2.1 强制性编码规范

    7.2.2 非强制性编码风格建议

package main
import "fmt"

func Foo(a,b int)(ret int,err error){
if a > b{
return a,nil
    }else{
return b,nil
    }
,nil
}

func
main() { i,_ := Foo(,)
fmt.Println("Hello,world",i)}

hello1

$ go fmt hello1.go

package main

import "fmt"

func Foo(a, b int) (ret int, err error) {
    if a > b {
        return a, nil
    } else {
        return b, nil
    }
    , nil
}

func main() {
    i, _ := Foo(, )
    fmt.Println("Hello,world", i)
}

test2

  7.3 远程import支持

package main

import (
    "fmt"
    "github.com/myteam/exp/crc32"
)

  7.4 工程组织

    7.4.1 GOPATH

export GOPATH=~/work/go-proj1:~/work2/goproj2:~/work3/work4/go-proj3

    7.4.2 目录结构

  7.5 文档管理

  7.6 工程构建

  7.7 跨平台开发

    7.7.1 交叉编译

    7.7.2 Android支持

  7.8 单元测试

  7.9 打包分发

  7.10 小结

第8章 开发工具

  8.1 选择开发工具

  8.2 gedit

    8.2.1 语法高亮

    8.2.2 编译环境

  8.3 Vim

  8.4 Eclipse

  8.5 Notepad++

    8.5.1 语法高亮

    8.5.2 编译环境

  8.6 LitelIDE

  8.7 小结

第9章 进阶话题

  9.1 反射

    9.1.1 基本概念

    9.1.2 基本用法

package main

import (
    "fmt"
    "reflect"
)

func main() {
    var x float64 = 3.4
    fmt.Println("type:",reflect.TypeOf(x))

    v := reflect.ValueOf(x)
    fmt.Println("type:",v.Type())
    fmt.Println("kind is float64:",v.Kind() ==reflect.Float64)
    fmt.Println("value:",v.Float())
}

reflect

package main

import (
    "fmt"
    "reflect"
)

func main() {
    var x float64 = 3.4
    p := reflect.ValueOf(&x)

    fmt.Println("type of p:",p.Type())
    fmt.Println("settability of p:",p.CanSet())

    v := p.Elem()
    fmt.Println("settability of v:",v.CanSet())

    v.SetFloat(7.1)
    fmt.Println(v.Interface())
    fmt.Println(x)
}

  9.1.3 对结构的反射操作

package main

import (
    "fmt"
    "reflect"
)

type T struct {
    A int
    B string
}

func main() {
    t := T{,"mh203"}
    s := reflect.ValueOf(&t).Elem()
    typeOfT := s.Type()

    ; i < s.NumField(); i++ {
        f := s.Field(i)
        fmt.Printf("%d: %s %s = %v\n",i,typeOfT.Field(i).Name,f.Type(),f.Interface())
    }
}

  9.2 语言交互性

package main

import "fmt"

/*
#include <stdlib.h>
*/
import "C"

func Random() int {
    return int(C.random())
}

func Seed(i int) {
    C.srandom(C.uinit(i))
}

func main() {
    Seed()
    fmt.Println("Random:",Random())
}

cgo1

package main

/*
#include <stdio.h>
void hello() {
    printf("Hello,Cgo! -- From C world.\n")
}
*/
import "C"

func Hello() int {
    return int(C.hello())
}

func main() {
    Hello()
}

// #cgo CFLAGS: -DPNG_DEBUG=1
// #cgo linux CFLAGS: -DLINUX=1
// #cgo LDFLAGS: -lpng
// #include <png.h>
import "C"

// #cgo pkg-config: png cairo
// #include <png.h>
import "C"

cgo2

    9.2.1 类型映射

    9.2.2 字符串映射

    9.2.3 C程序

    9.2.4 函数调用

    9.2.5 编译Cgo

  9.3 链接符号

  9.4 goroutine机理

    9.4.1 携程

    9.4.2 携程的C语言实现

    9.4.3 协程库概述

package main

import (
    "flag"
    "fmt"
    "os"
    "strconv"
)

var goal int

func primeTask(c chan int) {
    p := <-c

    if p > goal {
        os.Exit()
    }

    fmt.Println(p)

    nc := make(chan int)

    go primeTask(nc)

    for {
        i := <-c

         {
            nc <- i
        }
    }
}

func main() {
    flag.Parse()

    args := flag.Args()

     {
        var err error
        goal,err = strconv.Atoi(args[])
        if err != nil {
            goal =
        }
    } else {
        goal =
    }

    fmt.Println("goal=",goal)

    c := make(chan int)

    go primeTask(c)

    ;;i++ {
        c <- i
    }
}

primes

    9.4.4 任务

    9.4.5 任务调度

    9.4.6 上下文切换

    9.4.7 通信机制

  9.5 接口机理

    9.5.1 类型赋值给接口

package main

import "fmt"

type ISpeaker interface {
    Speak()
}

type SimpleSpeaker struct {
    Message string
}

func (speaker *SimpleSpeaker) Speak() {
    fmt.Println("I am speaking? ",speaker.Message)
}

func main() {
    var speaker ISpeaker
    speaker = &SimpleSpeaker{"Hell"}
    speaker.Speak()
}

interface-1

    9.5.2 接口查询

    9.5.3 接口赋值

Go语言编程 (许式伟 等 著)的更多相关文章

  1. 许式伟:我与Go语言的这十年[转]

    2017-12-18 许式伟 Go中国 2007 年 9 月 20 日,关于设计一门全新语言的讨论正式开始,这门全新的语言,就是后来的 Go.时至今日,Go 语言已经发布到 1.9 版本,走过了整整十 ...

  2. TOP100summit 2017 七牛云许式伟:不用JAVA和C语言,我为什么坚持Go语言

    本文编辑:Cynthia 2009年,谷歌发布第二款开源编程语言,Go语言.8年过去了,很多初创公司早期使用Go进行开发,包括云计算巨头Docker.而Go语言在中国的普及程度还比不上JAVA和C语言 ...

  3. C语言编程实现Linux命令——who

    C语言编程实现Linux命令--who 实践分析过程 who命令是查询当前登录的每个用户,它的输出包括用户名.终端类型.登录日期及远程主机,在Linux系统中输入who命令输出如下: 我们先man一下 ...

  4. 个人c语言编程风格总结

    总结一下我个人的编程风格及这样做的原因吧,其实是为了给实验室写一个统一的C语言编程规范才写的.首先声明,我下面提到的编程规范,是自己给自己定的,不是c语言里面规定的. 一件事情,做成和做好中间可能隔了 ...

  5. Linux下C语言编程实现spwd函数

    Linux下C语言编程实现spwd函数 介绍 spwd函数 功能:显示当前目录路径 实现:通过编译执行该代码,可在终端中输出当前路径 代码实现 代码链接 代码托管链接:spwd.c 所需结构体.函数. ...

  6. 七牛CEO许式伟:移动游戏资源存贮的大趋势

    (国内知名Android开发论坛eoe开发者社区推荐:http://www.eoeandroid.com/) 9月14日,eoe移动开发者大会正式在北京国家会议中心召开,七牛云储存CEO许式伟先生做了 ...

  7. 混合语言编程:启用CLR(公共语言运行时编译)让C#调用C++

    前言 关于混合C#和C++的编程方式,本人之前写过一篇博客(参见混合语言编程:C#使用原生的Directx和OpenGL),在之前的博客中,介绍了在C#的Winform和WPF下使用原生的Direct ...

  8. Linux基础与Linux下C语言编程基础

    Linux基础 1 Linux命令 如果使用GUI,Linux和Windows没有什么区别.Linux学习应用的一个特点是通过命令行进行使用. 登录Linux后,我们就可以在#或$符后面去输入命令,有 ...

  9. LINUX下C语言编程基础

    实验二 Linux下C语言编程基础 一.实验目的 1. 熟悉Linux系统下的开发环境 2. 熟悉vi的基本操作 3. 熟悉gcc编译器的基本原理 4. 熟练使用gcc编译器的常用选项 5 .熟练使用 ...

随机推荐

  1. (C/C++学习笔记) 二. 数据类型

    二. 数据类型 ● 数据类型和sizeof关键字(也是一个操作符) ※ 在现代半导体存储器中, 例如在随机存取存储器或闪存中, 位(bit)的两个值可以由存储电容器的两个层级的电荷表示(In mode ...

  2. innerHTML和innerText的区别,以及select元素中怎么取出被选中的option。

    一.innerHTML和innerText的区别. 元素.innerHTML = 字符串,是将一对或一个标签所标识的内容全部替换为所赋予的字符串,如果字符串中有标签,浏览器将自动识别其中的标签. 元素 ...

  3. spingmvc 访问静态文件,比如css,img等

    这里我来引用一段别人的原话 url-pattern有5种配置模式: (1)/xxx:完全匹配/xxx的路径 (2)/xxx/*:匹配以/xxx开头的路径,请求中必须包含xxx. (3)/*:匹配/下的 ...

  4. L314 单音节词读音规则(二)-元音字母发音规则

    1 单个元音发音尽量拖音一下(2S),发音会饱满一些. 2开音节: 辅音(辅组)(没有)+元音+辅音+e 的单词其中:元音发字母本身音,辅音字母不为r , 字母e不发音. 相对开音节:第一个元音都发字 ...

  5. winform 子窗体调用父窗体中的方法

    在父窗体里定义委托 public delegate void inis(string str); 在父窗体中定义要调用的方法 public void inigs(string gs) { textBo ...

  6. SQL注入之Sqli-labs系列第一关

    在开始接触渗透测试开始,最初玩的最多的就是Sql注入,注入神器阿D.明小子.穿山甲等一切工具风靡至今.当初都是以日站为乐趣,从安全法实施后在没有任何授权的情况下,要想练手只能本地环境进行练手,对于sq ...

  7. deconvolution layer parameter setting

    reference: 1. Paper describes initializing the deconv layer with bilinear filter coefficients and tr ...

  8. 【leetcode】69-Sqrt(x)

    problem Sqrt(x) code class Solution { public: int mySqrt(int x) {// x/b=b long long res = x;// while ...

  9. c日志宏

    仅供参考,不推荐 #ifdef _DEBUG #define LOGDEBUG(format, ...)\ {\ FILE *fp = fopen("nccli.log", &qu ...

  10. active在iphone上不起作用

    在js中加一个空的touchstart函数 $(function(){ document.body.addEventListener('touchstart',function(){ }); 或在&l ...