Go 入门笔记

Posted engchina

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Go 入门笔记相关的知识,希望对你有一定的参考价值。

Go 入门笔记

指针

指针是一种特殊类型,它的实例讲保存被引用对象的内存地址,而不是对象自身的值。

指针变量在声明后如果未获得有效的内存地址,那么它的默认值就是nil(空引用)。

示例代码,

package main

import "fmt"

func main() 
	var p1 *bool
	fmt.Println("p1 的默认值:", p1)
	var p2 *int8
	fmt.Println("p2 的默认值:", p2)
	var p3 *string
	fmt.Println("p3 的默认值:", p3)

输出结果,

p1 的默认值: <nil>
p2 的默认值: <nil>
p3 的默认值: <nil>

在类型名称前面加上"*"(星号)运算符,就是对应的指针类型。

在变量名称前面加上"&"运算符,就能获得该变量值的内存地址。其运算结果为指向该变量类型的指针。

示例代码,

package main

import "fmt"

func main() 
	var k = "abcdefg"
	var pk = &k
		fmt.Println("k 的内存地址是:", pk)

输出结果,

k 的内存地址是: 0xc00008a260

new 函数

new 函数为指定的类型分配内存空间,并使用类型的默认值进行初始化,最后返回新分配内存空间的地址。

new 函数的定义如下,

func new(Type) *Type

代码示例,

package main

import "fmt"

func main() 
	var px *int16 = new(int16)
	fmt.Printf("px 指向的内存地址: %p\\n", px)
	fmt.Printf("px 所指向对象的值: %v\\n", *px)

输出结果,

px 指向的内存地址: 0xc00001c0c8
px 所指向对象的值: 0

以下几点需要注意,

  • new(String) 所分配的值并不是 nil,而是空字符串(“”)。

  • 结构体分配内存空间后,会为其字段分配默认值。

  • 接口类型使用 new 函数分配内存空间后,其默认值为 nil(空指针)。

代码示例,

package main

import "fmt"

func main() 
	type sender interface 
		LineOut(data []byte) int
	

	var pi = new(sender)
	fmt.Println(*pi)

输出结果,

<nil>

iota 常量

iota 常量的定义如下,

const iota = 0

这是一个有特殊用途的常量,在批量定义常量的代码中(这些代码一般写在小括号中),如果常量 A 使用了 iota 常量作为基础整数值,那么在 A 之后定义的常量会自动累加。

代码示例,

package main

import "fmt"

const (
	A = iota
	B
	C
	D
)

func main() 
	fmt.Println("A:", A)
	fmt.Println("B:", B)
	fmt.Println("C:", C)
	fmt.Println("D:", D)

输出结果,

D:\\Users\\thinkpad\\AppData\\Local\\Temp\\GoLand\\___go_build_99_Learn.exe
A: 0
B: 1
C: 2
D: 3

当 iota 出现在常量列表的首位置时,它的值为 0,但随着出现的位置不同,iota 常量的值也会改变。

以下述代码为例,当定义 W 常量时,iota 的值为 4(第五个变量,从 0 开始计算),iota + 3 使得 W 的值为 7。

package main

import "fmt"

const (
	S = 17
	T = 9
	U = iota
	V = iota
	W = iota + 3
	X = iota + 3
	Y = iota + 3
	Z = iota + 3
)

func main() 
	fmt.Println("S:", S)
	fmt.Println("T:", T)
	fmt.Println("U:", U)
	fmt.Println("V:", V)
	fmt.Println("W:", W)
	fmt.Println("X:", X)
	fmt.Println("Y:", Y)
	fmt.Println("Z:", Z)

输出结果,

S: 17
T: 9
U: 2
V: 3
W: 7
X: 8
Y: 9
Z: 10

未完待续!

Go入门笔记

《Go程序设计语言》作者Kerninghan教授与谷歌GO开发团队核心成员联合编写,Go语言编程圣经。本笔记是学习翻阅此书中文翻译版,整理而成。 非常感谢李道兵、 高博等辛苦的翻译。
Go IDE-Golang 使用入门参考如下。
https://www.2cto.com/kf/201704/632395.html

Go语言简介

【1】Go语言是编译型语言。Go 的工具链将程序的源文件转变成机器相关的二进制指令。Go代码是使用包来组织的,包类似于其他语言的模块。一个包由一个或者多个go文件组成,放在同一个文件夹中,文件夹的名字描述了包的作用。每一个源文件的开始都使用package声明,指明了这个文件属于哪个包。
【2】import 必须在package声明后面,import导入声明后面是组成程序的函数、变量、常量、类型(func、var、const、type)开头声明。大部分情况下声明的顺序是没有关系的。
【3】Go不需要在语句或者声明后面使用分号结尾,除非有多个语句或者声明出现在同一行。Go代码格式化要求非常严格。
【4】Go不允许存在无用的变量或者无用的包导入,不然会出现编译错误。如果有些变量返回必须需要变量占位,可以使用空标识符”_”。空标识符可以用在任何语法需要变量名但是程序逻辑不需要的地方,例如丢掉每次迭代产生的无用的索引。
【5】“:=”是Go语言中特有的短变量声明和初始化,更加简洁,但是通常在一个函数的内部使用,不适合包级别的变量。

// = 使用必须使用先var声明例如:
var a
a=100
//或
var b = 100
//或
var c int = 100
// := 是声明并赋值,并且系统自动推断类型,不需要var关键字
d := 100

进程 线程 协程

进程:独立的栈空间,独立的堆空间,进程之间调度由os完成。
线程:独立的栈空间,共享堆空间,内核线程之间调度由os完成。
协程:独立的栈空间,共享堆空间,调度由用户自己控制,本质上有点类似于用户级线程,这些用户级线程的调度也是自己实现的。

goroutine-channel-select

参考链接:http://blog.csdn.net/qwertyupoiuytr/article/details/55101258
goroutine:原生支持语言级并发,这个并发的最小逻辑单元就是goroutine。goroutine就是Go语言提供的一种用户态线程,这种用户态线程是跑在内核级线程之上的,goroutine在运行时的调度是由Go语言提供的调度器来进行的,创建一个goroutine使用关键字go,go创建的goroutine不会阻塞主线程:
go func_name()

channel:Channel是Go中的一个核心类型,可以把它看成一个管道,通过它可以发送或者接收数据进行通讯(communication)。配合goroutine,形成了一种既简单又强大的请求处理模型。
channel的基本操作:

var c chan int   //声明一个int类型的channel,注意,该语句仅声明,不初始化channel
c := make(chan type_name)   //创建一个无缓冲的type_name型的channel,无缓冲的channel当放入1个元素后,后续的输入便会阻塞
c := make(chan type_name, 100)   //创建一个缓冲区大小为100的type_name型的channel
c <- x   //将x发送到channel c中,如果channel缓冲区满,则阻塞当前goroutine
<- c   //从channel c中接收一个值,如果缓冲区为空,则阻塞
x = <- c   //从channel c中接收一个值并存到x中,如果缓冲区为空,则阻塞
x, ok = <- c   //从channel c中接收一个值,如果channel关闭了,那么ok为false(在没有defaultselect语句的前提下),在channel未关闭且为空的情况下,仍然阻塞
close(c)   //关闭channel c
for term := range c    //等待并取出channelc中的值,直到channel关闭,会阻塞
单向channel:
var ch1 chan<- float64    //只能向里面写入float64的数据,不能读取
var ch2 <-chan int        //只能读取int型数据

select:select用于在多个channel上同时进行侦听并收发消息,当任何一个case满足条件时即执行,如果没有可执行的case则会执行default的case,如果没有指定defaultcase,则会阻塞程序,select的语法:

func TestChannel()

    // For our example we'll select across two channels.
    c1 := make(chan string)
    c2 := make(chan string)

    // Each channel will receive a value after some amount
    // of time, to simulate e.g. blocking RPC operations
    // executing in concurrent goroutines.
    go func() 
        time.Sleep(time.Second * 1)
        c1 <- "one"
    ()
    go func() 
        time.Sleep(time.Second * 2)
        c2 <- "two"
    ()

    // We'll use `select` to await both of these values
    // simultaneously, printing each one as it arrives.
    for i := 0; i < 2; i++ 
        select 
            case msg1 := <-c1:
                fmt.Println("received", msg1)
            case msg2 := <-c2:
                fmt.Println("received", msg2)
        
    


Go Web简单例子

package server

import (
    "net/http"
    "fmt"
    "log"
    "ch01/lissajous"
)




func Server1() 

    http.HandleFunc("/", handler)
    log.Fatal(http.ListenAndServe("localhost:8000", nil))



func handler(w http.ResponseWriter,r *http.Request) 
    fmt.Fprintf(w,"URL.PATH = %q\\n",r.URL.Path)
    lissajous.Lissajous(w)

以上是关于Go 入门笔记的主要内容,如果未能解决你的问题,请参考以下文章

Go语言自学系列 | 高效golang开发

Go语言自学系列 | golang开发工具

Go语言自学系列 | golang开发vscode快捷键

Go 语言入门很简单:什么是 Golang

Go语言入门经典|文末赠书

golang语言入门及安装