go语言学习笔记

1、如果声明了的变量,或则引入了进来的包是没用过的,那么编译失败,status return 2,但是如果是一个全局变量不用,是可以的。

2、已经赋值了的变量不能再次赋值,不能用 := 再次赋值。但是是可以用 = 继续赋值的。

package main
import (
    "fmt" 
)
func main() {
    var c int = 2;
    var d = 2;
    d = 3; // can not use := replace the d
    fmt.Println(c);
    fmt.Println(d);
}
View Code

3、不存在的变量可以直接用,d := 3直接用。但是不能d = 3这样。这样会提示引用不存在的变量。  但是直接用的,也不能声明在全局变量。

4、for语句变化太多了,不能加括号,也只能用 i++

package main
import (
    "fmt"
)


const (
    a = iota;
    b = iota; //这个iota没什么用的。
    c;
    d;    
)

func main() {
    for i := 0; i < 5; i++ { // 只能这样, i++。。而且不能有括号。
        fmt.Println(i);
    }
}
View Code

5、感觉go语言其实就是类型后置了,确实有很多简便的地方,但是我还是想为每一个变量都声明一个类型。这样好看点。

package main

import (
    "fmt"
    "unsafe"
)

const (
    a = iota
    b = iota
    c
    d
)

func getMax(a, b int) int { //确实可以这样使得a和b都是int,但是不习惯
    if a > b {
        return a
    } else {
        return b
    }
}

func toShow(a int, b float32, c int) (int, float32, int) { // 函数定义了,不用
    return a, b, c
}

func main() {
    var str string = "12454353242434"
    fmt.Println(unsafe.Sizeof(str))
    var sz int = len(str)
    fmt.Println(sz)
    fmt.Println(getMax(1, 2))
    fmt.Println(toShow(1, 2, 3))
}
View Code

6、返回函数的函数。new功能,而且可以使用同一个变量一直用。称为函数的闭包

package main

import (
    "fmt"
)

func getSequence() func() int { // 返回类型是 func() int
    var i int = 0
    return func() int {
        i++
        return i
    }
}

//带参数的函数
func getAddSequence() func(x int, y int) (int, int, int) { // 函数都是匿名的
    var number int = 0
    return func(x int, y int) (int, int, int) {
        number++
        return number, x, y
    }
}

func main() {
    var nextNumber func() int = getSequence() // type func() int
    fmt.Println(nextNumber())

    var nextAddNumber func(int, int) (int, int, int) = getAddSequence()
    fmt.Println(nextAddNumber(1, 2)) // type  func(int, int) (int, int, int)
}
View Code

7、数组初始化,居然不能array[0] = array[1] = 1;

分开来就行,我怀念c++了。

package main

import (
    "fmt"
)

func getSequence() func() int { // 返回类型是 func() int
    var i int = 0
    return func() int {
        i++
        return i
    }
}

//带参数的函数
func getAddSequence() func(x int, y int) (int, int, int) { // 函数都是匿名的
    var number int = 0
    return func(x int, y int) (int, int, int) {
        number++
        return number, x, y
    }
}

func main() {
    var nextNumber func() int = getSequence() // type func() int
    fmt.Println(nextNumber())

    var nextAddNumber func(int, int) (int, int, int) = getAddSequence()
    fmt.Println(nextAddNumber(1, 2)) // type  func(int, int) (int, int, int)

    var arrayc [2]int
    arrayc[0] = arrayc[1] = 1;
    

    var array = [3]int{0, 1, 2} // 数组直接初始化,要这样,先等于
    for i := 0; i < len(array); i++ {
        fmt.Println(i)
    }
}
View Code

8、go语言中不用考虑变量的生存周期,系统会自动回收,或则自动保留。但是还是要注意效率问题。

这里显示结构体初始化方法(一直忘记T__T)

package main

import "fmt"

type speakable interface {
    speak()
}

type Person struct {
    a int
    b int
}

func (person *Person) speak() int {
    return person.a + person.b
}

func (person *Person) call() {
    fmt.Println("fff")
}

func main() {
    person := Person{a: 1, b: 2} // atttion
    fmt.Println(person.speak())
    person.call()
}
View Code

9、做了一个题目,学习了go'语言的输入是怎样的

http://codeforces.com/problemset/problem/914/A

package main

two methond for scan

package main

import (
    "bufio"
    "fmt"
    "math"
    "os"
    "strconv"
)

func get(s *bufio.Scanner) int {
    succ := s.Scan()
    if !succ {
        for {

        }
    }
    res, _ := strconv.ParseInt(s.Text(), 10, 0)
    return int(res)
}

func main() {
    var n int
    // var a int

    s := bufio.NewScanner(os.Stdin)
    s.Split(bufio.ScanWords)

    n = get(s)
    ans := -19999999
    for i := 0; i < n; i++ {
        var a int
        a = get(s)
        if a < 0 {
            if ans < a {
                ans = a
            }
        } else {
            t := int(math.Floor(math.Sqrt(float64(a))))
            if t*t != a && ans < a {
                ans = a
            }
        }
    }
    fmt.Println(ans)
}
View Code
package main

import "fmt"
import (
    "bufio"
    "math"
    "os"
)

func main() {
    var n int
    // var a int
    input := bufio.NewReader(os.Stdin)
    fmt.Fscan(input, &n)

    ans := -19999999
    for i := 0; i < n; i++ {
        var a int
        fmt.Fscan(input, &a)
        if a < 0 {
            if ans < a {
                ans = a
            }
        } else {
            t := int(math.Floor(math.Sqrt(float64(a))))
            if t*t != a && ans < a {
                ans = a
            }
        }
    }
    fmt.Println(ans)
}
View Code

 日期的题目,只能用第一种输入

package main

import (
    "bufio"
    "fmt"
    "os"
    "strconv"
    "time"
)

func str2Time(str string) time.Time {
    loc, _ := time.LoadLocation("Local")
    the_time, _ := time.ParseInLocation("2006-01-02", str, loc)
    return the_time
}

func getInt(s *bufio.Scanner) int {
    succ := s.Scan()
    if !succ {
        for {

        }
    }
    res, _ := strconv.ParseInt(s.Text(), 10, 0)
    return int(res)
}

func getStr(s *bufio.Scanner) string {
    succ := s.Scan()
    if !succ {
        for {

        }
    }
    return s.Text()
}

var local int

func ok(str1 string) int {
    str := str1[:4]
    str += str1[5:7]
    str += str1[8:10]
    be, en := 0, 7
    for {
        if be >= en {
            return 1
        }
        if str[be] != str[en] {
            return 0
        }
        be++
        en--
    }
    return 0
}

func main() {
    day, _ := time.ParseDuration("24h")
    var n int
    s := bufio.NewScanner(os.Stdin)
    s.Split(bufio.ScanWords)
    n = getInt(s)
    for i := 0; i < n; i++ {
        var be, en string
        be = getStr(s)
        en = getStr(s)

        beTime := str2Time(be)
        enTime := str2Time(en)
        enTime = enTime.Add(day)
        ans := 0
        for ; beTime.Before(enTime); beTime = beTime.Add(day) {
            ans += ok(beTime.String()[:10])
        }
        fmt.Println(ans)
    }
}
View Code

10、关于指针变量方法的

常量方法,明显可以转换成一个指针方法

func (p struct) fun() {}   换转换成一个  func(p *struct) fun() {  (*p).fun() } 这样转换,毫无损失

但是指针变量方法就不能转换成常量变量方法了,因为

fun (p *struct) fun() { 可能要改变*p的值 } 你变成了 fun(p struct) fun() { (&p).fun() },这里改变的会是形参p的值,和预期不同。

指针方法,编译器帮我们转换了,变成(&t).xxx

package main

import (
    "fmt"
)

type face interface {
    value_show()
    point_show()
}

type Interger int

func (a Interger) value_show() {
    fmt.Println(a)
}

func (a *Interger) point_show() {
    fmt.Println(*a)
}

func main() {
    var point *Interger = new(Interger)
    *point = 12

    point.point_show() // correct
    point.value_show() // correct,这个因为编译器会帮value_show生成一个指针版本

    var value Interger = 333
    value.value_show() // correct
    value.point_show() // 这个非指针变量,为什么可以调用point_show方法???
    //(&value).point_show() // 隐式转换成这个样子

    //测试,开一个接口,证明非指针变量并没有完全实现接口要求的所有方法,所以不能赋值

    var test_point face = point // ok it`s correct,编译没错误
    fmt.Println(test_point)

    var test_value face = value //这里会报错的,没有实现point_show方法
    fmt.Println(test_value)
}
View Code

11、接口类型查询,要询问某个接口变量是否是xxx接口,只需要   _, ok := value.(xxx),如果是,则ok放回true,要注意那个xxx只能填入接口类型

12、查询是否某个数据类型:switch v := v1.(type) { case int:  case string: }

这个骚东西,需要v1是接口类型才可以的,所以需要

func show(x interface{}) {
    switch x.(type) {
    case string:
        fmt.Println(1)
    case int:
        fmt.Println(2)
    case []string:
        fmt.Println(3)
    case map[string][]string:
        fmt.Println(4)
    }
}
View Code

也可以使用放射机制:http://blog.sina.com.cn/s/blog_487109d101013g2p.html

package main

import (
    "encoding/json"
    "fmt"
    "reflect"
)

type vimi struct {
    Mp map[string][]string `json : "haha"`
    // Ch chan int
}

func show(x interface{}) {
    switch x.(type) {
    case string:
        fmt.Println(1)
    case int:
        fmt.Println(2)
    case []string:
        fmt.Println(3)
    case map[string][]string:
        fmt.Println(4)
    }
}

func main() {
    var test vimi
    // test.Ch = make(chan int, 4)
    // test.Ch <- 1
    test.Mp = make(map[string][]string)
    test.Mp["vimi"] = append(test.Mp["vimi"], "test_one")
    test.Mp["vimi"] = append(test.Mp["vimi"], "test_two")
    fmt.Printf("%+v
", test)

    res, er := json.Marshal(test)
    fmt.Println(er)
    fmt.Println(string(res))

    mp := make(map[string][]string)
    mp["vimi"] = append(mp["vimi"], "baby_one")
    mp["vimi"] = append(mp["vimi"], "baby_two")
    mp_json, _ := json.Marshal(mp)
    fmt.Println(string(mp_json))

    ch := make(chan int, 4)
    ch <- 1
    ch <- 2
    ch <- 3
    ch_json, err := json.Marshal(ch)
    fmt.Println(err)
    fmt.Println(string(ch_json))

    fmt.Println("-----")
    fmt.Println(reflect.TypeOf(mp))
    show(mp)
}
reflect

13、go语言用json的时候,struct里面的字段开头字母都要大写啊啊啊啊啊,不然读入不成功日日日,也可能需要P109

package main

import (
    "encoding/json"
    "fmt"
)

type test_json struct { 
    Id   string  //这个一定要大写
    Name string
}

const js = `{"name":"vimi", "id":"2015"}  
                {"name":"stupidone", "id":"2014"}`

var jjss = []byte(`[{"name": "vimi", "id": "2015"},
                {"name": "stupidone", "id": "2014"}]`)

var jsonBlob = []byte(`[
        {"Name": "Platypus", "Order": "Monotremata"},
        {"Name": "Quoll",    "Order": "Dasyuromorphia"}
    ]`)

type Animal struct {
    Name  string
    Order string
}

// 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!"}
//     `

func main() {
    var a []test_json
    err := json.Unmarshal(jjss, &a)
    fmt.Println(err)
    fmt.Println(a)
    fmt.Printf("%+v", a)

    // var animals []Animal
    // err := json.Unmarshal(jsonBlob, &animals)
    // if err != nil {
    //     fmt.Println("error:", err)
    // }
    // fmt.Printf("%+v", animals)
}
一定要大写

14、一个[]byte的json字节数组,只能转化成一个struct

package main

import (
    "encoding/json"
    "fmt"
    // "io"
    // "strings"
)

type test_json struct {
    Name string
    Id   int
}

const js = `{"name":"vimi", "id":"2015"}  
                {"name":"stupidone", "id":"2014"}`

var jjss = []byte(`[{"name":"vimi", "id":2015},
                {"name":"stupidone", "id":2014}]`)

// 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!"}
//     `

func main() {
    var a test_json
    a.Id = 2015
    a.Name = "刘炜铭"
    var b []byte
    var err error
    b, err = json.Marshal(a)
    fmt.Println(b, err)

    var _a_ test_json
    liu := json.Unmarshal(b, &_a_) // 一个这样的[]byte类型,只能转成一个实例,所以这里_a_不是数组
    fmt.Println(liu)
    fmt.Printf("%+v", _a_)

    // dec := json.NewDecoder(strings.NewReader(js))
    // for {
    //     var m test_json
    //     err := dec.Decode(&m)
    //     if err == io.EOF {
    //         break
    //     } else if err != nil {
    //         // fmt.Println("ff")
    //     }
    //     fmt.Println(m.Name, m.Id)
    // }
}
View Code

但是这的jjss也只是一个[]byte而已,编译额时候就叫我传数组了,检测到了吗

package main

import (
    "encoding/json"
    "fmt"
    // "io"
    // "strings"
)

type test_json struct {
    Name string
    Id   int
}

const js = `{"name":"vimi", "id":"2015"}  
                {"name":"stupidone", "id":"2014"}`

var jjss = []byte(`[{"name":"vimi", "id":2015},
                {"name":"stupidone", "id":2014}]`)

// 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!"}
//     `

func main() {
    var a test_json
    a.Id = 2015
    a.Name = "刘炜铭"
    var b []byte
    var err error
    b, err = json.Marshal(a)
    fmt.Println(b, err)

    var _a_ []test_json
    liu := json.Unmarshal(jjss, &_a_) // 一个这样的[]byte类型,只能转成一个实例,所以这里_a_不是数组
    fmt.Println(liu)
    fmt.Printf("%+v", _a_)

    // dec := json.NewDecoder(strings.NewReader(js))
    // for {
    //     var m test_json
    //     err := dec.Decode(&m)
    //     if err == io.EOF {
    //         break
    //     } else if err != nil {
    //         // fmt.Println("ff")
    //     }
    //     fmt.Println(m.Name, m.Id)
    // }
}
View Code

即使jjss是一个struct的信息,也是传数组

15、不知道为什么同一个包中,不能问各自的变量,但是在不同的包中是可以的。只需要导入对应的包就行。但是在同一个包中是不可以导入包的因为这样会导致重复导入。没解决,但是只要你代码没写错在不同的包中是可以运行的。。

16、要使你的任何东西,在其他包中可见,就必须要大写字母开头。包括一个结构体的里面的字段名, OR 函数

--------------------------------------2018年01月29日16:42:24-------------------------------------------

package main

import (
    "fmt"
    "log"
    "net/http"
    "strings"
)

func sayHelloName(w http.ResponseWriter, r *http.Request) {
    fmt.Println("-------------------")
    r.ParseForm()
    fmt.Println("----", r)

    fmt.Println(r.Form)
    fmt.Println("path : ", r.URL.Path)
    fmt.Println("scheme : ", r.URL.Scheme)

    fmt.Println("r.Form : ", r.Form["url_log"])
    for k, v := range r.Form {
        fmt.Println("key:", k)
        fmt.Println("value:", strings.Join(v, " "))
    }
    fmt.Fprint(w, "Hello")
}

func main() {
    http.HandleFunc("/", sayHelloName)
    err := http.ListenAndServe(":9090", nil)
    if err != nil {
        log.Fatal("listen and serve: ", err)
    }
}
简单http服务器

.gtpl路径,代码上用的是相对路径,怎么知道呢,创建一个文件看看就知道了

go run创建的相对目录会在.exec目录下,但是自己go build的,运行后却不在对应目录下。(OS 9中),windows的正常

package main

import (
    "fmt"
    "html/template"
    "log"
    "net/http"
    "strings"
)

func sayHelloName(w http.ResponseWriter, r *http.Request) {
    fmt.Println("-------------------")
    fmt.Println("-------------------")
    r.ParseForm()
    fmt.Println(r.Method)
    //fmt.Println("----", r)

    fmt.Println(r.Form)
    fmt.Println("path : ", r.URL.Path)
    fmt.Println("scheme : ", r.URL.Scheme)

    fmt.Println("r.Form : ", r.Form["url_log"])
    for k, v := range r.Form {
        fmt.Println("key:", k)
        fmt.Println("value:", strings.Join(v, " "))
    }
    fmt.Fprint(w, "Hello")
}

func login(w http.ResponseWriter, r *http.Request) {
    fmt.Println("********************")
    r.ParseForm()
    fmt.Println("method : ", r.Method)

    if r.Method == "GET" {
        t, err := template.ParseFiles("login.gtpl") //这里是相对路径的
        log.Println(t.Execute(w, nil))
    } else {
        r.ParseForm()
        fmt.Println("username : ", r.Form["username"])
        fmt.Println("password : ", r.Form["password"])
    }
}

func main() {
    /*不知道相对路径的,可以用os.create来看看系统是在那里创建的*/
    http.HandleFunc("/", sayHelloName)
    http.HandleFunc("/login", login)
    err := http.ListenAndServe(":9090", nil)
    if err != nil {
        log.Fatal("listen and serve: ", err)
    }
}
忘记的技巧

初始化字段,和C++一样的Node{},这里用了 花括号{}

package main

import (
    "fmt"
)

type Node struct {
    mp map[string][]string
    ch chan int
}

func main() {
    var vimi Node = Node{make(map[string][]string), make(chan int, 4)}
    vimi.mp["vimi"] = []string{"test_one", "test_two"}
}
init_二维

json不能解析map吗? && json.MarshalIndent

不是的,是因为json不能解析chan,一切都是因为有了chan。还有要注意变量全部得大写,才可以json成功。还有可以把err输出出来看看的

package main

import (
    "encoding/json"
    "fmt"
)

type Node struct {
    Mp  map[string][]string
    MMM map[string]int
    Ch  chan int
}

type Test struct {
    Name string `json : "vimi"`
}

func main() {
    var vimi Node = Node{make(map[string][]string), make(map[string]int), make(chan int, 4)}
    vimi.Mp["vimi"] = []string{"test_one", "test_two"}
    vimi.MMM["vimi"] = 2
    vimi.Ch <- 2
    res_by, _ := json.MarshalIndent(vimi, "", "	")
    fmt.Println(string(res_by))

    var vimi_test Test = Test{"vimi"}
    res_test, _ := json.MarshalIndent(vimi_test, "", "	")
    fmt.Println(string(res_test))
}
josn.MarshalIndent

解析json中,json.Unmarshal(date, interface{})中,interface应该传怎样的参数

首先回顾一下,C语言的memset

http://www.cnblogs.com/liuweimingcprogram/p/4973254.html

而且,用reflect.TypeOf可以知道数据类型,用unsafe.Sizeof可以知道数据大小。那么够了

首先:传指针和传变量的一个大区别就是能否改变值。传变量一般都是值传递(引用类型除外)

那么,传指针是肯定的了。

然后:

&p : 地址 + sizeof = 8

&&p :地址 + sizeof = 8

明显,地址的地址,还是那个地址(数值上)

加上有sizeof固定死了。解引用的时候也会做到一个一个解引用。所以这两种方法都是可以的。

-----------------------------------------------------------------------------------------------------------------------------------------------

1、在某个时间点运行程序,可以用

timer1 := time.NewTimer(time.Second * 2)
<-timer1.C
fmt.Println("Timer 1 expired")

2、上面那个是,2秒后,放一个ch去timer.C,但是如果想一直运行的,可以用Ticker,每隔2秒放一次

不stop,就一直放

package main

import (
    "fmt"
    "time"
)

func main() {
    t := time.NewTicker(time.Second)
    go func() {
        for r := range t.C {
            fmt.Println(r)
        }
    }()
    time.Sleep(time.Second * 5)
    t.Stop()
    fmt.Println("finish")
}

3、go语言中, 那个os.Args[0]代表有多少个参数,空格分开的。传入的话,用

client.exe 127.0.0.1

那么os.Args[0] = 1

os.Args[1] = "127.0.0.1"

千万不要加--,被坑了

【这个是错误的】

----------------------------------------------------2018-05-23 15:34:33-------------------------------------------------------------------

1、go中flags的使用

go run main.go --word 23 -numb 2 --fork --svar f

wordPtr := flag.String("word", "foo", "a string")   放回一个string的指针,解析附带的参数中 --word后面的字段,如果为空,则是foo(默认字段)


var svar string
flag.StringVar(&svar, "svar", "bar", "a string var")  不想用指针也可以这样的

boolPtr := flag.Bool("fork", false, "a bool")  特别要注意的是bool变量,只要加上 --fork字段,就是true,不加就是false,不需要--fork true这样,会错误的

// Once all flags are declared, call `flag.Parse()`
// to execute the command-line parsing.
flag.Parse()    开始解析

// [_Command-line flags_](http://en.wikipedia.org/wiki/Command-line_interface#Command-line_option)
// are a common way to specify options for command-line
// programs. For example, in `wc -l` the `-l` is a
// command-line flag.

package main

// Go provides a `flag` package supporting basic
// command-line flag parsing. We'll use this package to
// implement our example command-line program.
import (
    "flag"
    "fmt"
    "os"
)

func main() {

    // Basic flag declarations are available for string,
    // integer, and boolean options. Here we declare a
    // string flag `word` with a default value `"foo"`
    // and a short description. This `flag.String` function
    // returns a string pointer (not a string value);
    // we'll see how to use this pointer below.
    wordPtr := flag.String("word", "foo", "a string")

    // This declares `numb` and `fork` flags, using a
    // similar approach to the `word` flag.
    numbPtr := flag.Int("numb", 42, "an int")
    boolPtr := flag.Bool("fork", false, "a bool")

    // It's also possible to declare an option that uses an
    // existing var declared elsewhere in the program.
    // Note that we need to pass in a pointer to the flag
    // declaration function.
    var svar string
    flag.StringVar(&svar, "svar", "bar", "a string var")

    // Once all flags are declared, call `flag.Parse()`
    // to execute the command-line parsing.
    flag.Parse()

    // Here we'll just dump out the parsed options and
    // any trailing positional arguments. Note that we
    // need to dereference the pointers with e.g. `*wordPtr`
    // to get the actual option values.
    fmt.Println("word:", *wordPtr)
    fmt.Println("numb:", *numbPtr)
    fmt.Println("fork:", *boolPtr)
    fmt.Println("svar:", svar)
    fmt.Println("tail:", flag.Args())

    fmt.Println(os.Args)
}
go by example

如果需要使用os.Getenv("Telegram_Token")这样的话,需要在~/.zshrc文件中添加

export Telegram_Token=xxxxx

然后,select{}的话是一个死循环,直到有一个被触发了

golang静态编译,什么是静态编译?

https://tonybai.com/2017/06/27/an-intro-about-go-portability/

------------------------------- 2018年10月16日15:39:11 -------------------------------------

go语言的文件分成三种:

1、命令源码文件(有main函数的,然后goinstall的话会放去你的gobin目录下,go build的话生成在当前目录)

2、库源码文件 (就是没有main的,然后goinstall的话会放去pkg名录下以.a结尾,go build的话是没有用的,只会检查语法)

3、测试文件。

go get中:

-x : 也是显示

-u : 更新已经下载过的包

-fix : 转换编译版本到本地最新那个go-1.10

原文地址:https://www.cnblogs.com/liuweimingcprogram/p/8336295.html