Go的学习日记

1. 下载安装go

下载地址

2. 正常的打印

主函数的包名必须是main。。。

package main
import "fmt"

fuc main(){//go中{不可以单独一行,c++的同学注意了
   fmt.print("hello world")//伟大的开始
}

3. 声明定义一个变量

go不存在声明却未使用的变量

也就是说,单独写这么一句,你会发现他报错了

var a int = 1

你必须使用这个变量,哪怕只是打印一下,来解决报错。(令我非常吃惊)

差点忘了说了,全局变量无视此规则…

定义变量的几种方法,这里还需要特殊说明一下,Go没有char类型!!!

var a int = 1
var b,c int =2,3
d,e := 4,5//自动推断数据类型贼赞
//这里还需要补充一下,:是初始化声明,也就是说在下面
e:=4//报错
e=4//没问题

4. 常量Const,iota

const不想多说,主要是iota这个特殊常量,会在const关键字出现时被重置为0(内部),每新增一行计数器加一

有趣的写法

const(
	a = iota//0
    b = iota//1
    c = iota//2
)
const(
	a = 1<<iota//1
    b = 3<<iota//6
)

这里还要说明一下<<左移指令,1左移0位,依旧是1。3的二进制11左移一位变为110,即6。

注:<

5. 条件

写法需要注意的是条件判断没有括号

if a < 20{
    ...
} else{
    ...
}

6. 分支

写法

switch a{
    case v1:
    ...
    case v2:
    ...
    default:
    ...
}

7. 循环

只有for一种写法真心挺好的,它涵盖了所有的用法

//类c
for i:=1;i<2;i++{
    ...
}
//类while
for condition{
    ...
}
//无脑死循环
for{
    ...
}

8. 函数

写法

func name(v1,v2 类型) 返回类型{
    return 
} 
//Go可以返回多个值
fuc name(v1,v2, int) (int,int){
    return v1,v2
}

9. 数组

声明与初始化

//定义
var a [size] type
//初始化,这里可以不用规定数组大小
var a = [5]int{1,2,3,4,5}

10. 指针

这个没什么好说的,但是记录一下

var p *int
a := 1
p = &a
fmt.print(*p,p,&p)
//输出
1,a地址,p地址

11. 结构体

与c相似没什么好说的,就是不太明白为啥Go不面向对象

type Books struct {
   title string
   author string
   subject string
   book_id int
}

func main() {
   var Book1 Books        /* 声明 Book1 为 Books 类型 */
   var Book2 Books        /* 声明 Book2 为 Books 类型 */

   /* book 1 描述 */
   Book1.title = "Go 语言"
   Book1.author = "asd"
   Book1.subject = "Go 语言教程"
   Book1.book_id = 6495407

   /* book 2 描述 */
   Book2.title = "Python 教程"
   Book2.author = "asd"
   Book2.subject = "Python 语言教程"
   Book2.book_id = 6495700

   /* 打印 Book1 信息 */
   fmt.Printf( "Book 1 title : %s\n", Book1.title)
   fmt.Printf( "Book 1 author : %s\n", Book1.author)
   fmt.Printf( "Book 1 subject : %s\n", Book1.subject)
   fmt.Printf( "Book 1 book_id : %d\n", Book1.book_id)

   /* 打印 Book2 信息 */
   fmt.Printf( "Book 2 title : %s\n", Book2.title)
   fmt.Printf( "Book 2 author : %s\n", Book2.author)
   fmt.Printf( "Book 2 subject : %s\n", Book2.subject)
   fmt.Printf( "Book 2 book_id : %d\n", Book2.book_id)
}

12. 迭代

通过range

nums := []int{2, 3, 4}
	sum := 0
	//迭代数组
	for num := range nums {
		sum += num
	}
	fmt.Println("sum:", sum)
	//迭代map
	kvs := map[string]string{"a": "apple", "b": "banana"}
	for k, v := range kvs {
		fmt.Printf("%s -> %s\n", k, v)
	}

13. make

这个方法需要单独拿出来说

make(类型,size,长度)
//规定目前长度是1,最大长度是1,后面的参数可以不写
a := make([]int,1,1)
//定义map的主要方式,不通过make定义的map为一个空map,经测试,无法插入元素
b := make(map[string]string)
//可以直接这么插入,可扩容
b["abc"]="bca"
//定义长度是1,所以只能操作一个元素,后面的元素可以通过append增加,无视规定的最大长度
a[0]=1
a = append(a, 2)

14. 类型转换

var sum int = 17
var count int = 5
var mean float32   
mean = float32(sum)/float32(count)
fmt.Printf("mean 的值为: %f\n",mean)

15. 接口

不得不说,从Java过来看这块真的是有够痛苦,不过多看几遍吧

type Phone interface {
    call()
}

type NokiaPhone struct {
}

func (nokiaPhone NokiaPhone) call() {
    fmt.Println("I am Nokia, I can call you!")
}

type IPhone struct {
}

func (iPhone IPhone) call() {
    fmt.Println("I am iPhone, I can call you!")
}

func main() {
    var phone Phone

    phone = new(NokiaPhone)
    phone.call()

    phone = new(IPhone)
    phone.call()

}

16. 并发

go开启一个线程真的好简单

import (
        "fmt"
        "time"
)

func say(s string) {
        for i := 0; i < 5; i++ {
                time.Sleep(100 * time.Millisecond)
                fmt.Println(s)
        }
}

func main() {
        go say("world")
        say("hello")
}

channel这个东西过分强大

ch <- v    // 把 v 发送到通道 ch
v := <-ch  // 从 ch 接收数据
           // 并把值赋给 v
//通道的声明方式
ch := make(chan int)

实例

package main

import "fmt"

func sum(s []int, c chan int) {
        sum := 0
        for _, v := range s {
                sum += v
        }
        c <- sum // 把 sum 发送到通道 c
}

func main() {
        s := []int{7, 2, 8, -9, 4, 0}

        c := make(chan int)
        go sum(s[:len(s)/2], c)
        go sum(s[len(s)/2:], c)
        x, y := <-c, <-c // 从通道 c 中接收

        fmt.Println(x, y, x+y)
}

go为channel设置了缓冲区

通过make的第二个参数可以设置缓冲区的大小

ch := make(chan int, 100)

带缓冲区的通道允许发送端的数据发送和接收端的数据获取处于异步状态,就是说发送端发送的数据可以放在缓冲区里面,可以等待接收端去获取数据,而不是立刻需要接收端去获取数据。

不过由于缓冲区的大小是有限的,所以还是必须有接收端来接收数据的,否则缓冲区一满,数据发送端就无法再发送数据了。

注意:如果通道不带缓冲,发送方会阻塞直到接收方从通道中接收了值。如果通道带缓冲,发送方则会阻塞直到发送的值被拷贝到缓冲区内;如果缓冲区已满,则意味着需要等待直到某个接收方获取到一个值。接收方在有值可以接收之前会一直阻塞。

没有缓冲的缺点

如果只有读端,没有写端,那么 “读端”阻塞。
如果只有写端,没有读端,那么 “写端”阻塞。

实例

func main() {
    // 这里我们定义了一个可以存储整数类型的带缓冲通道
        // 缓冲区大小为2
        ch := make(chan int, 2)

        // 因为 ch 是带缓冲的通道,我们可以同时发送两个数据
        // 而不用立刻需要去同步读取数据
        ch <- 1
        ch <- 2

        // 获取这两个数据
        fmt.Println(<-ch)
        fmt.Println(<-ch)
}

遍历和关闭channel

close(c)//关闭通道
//遍历通道
for i := range c{
    ...
}

你可能感兴趣的:(Go的学习日记)