go入门笔记

package main

import (

"errors"

"fmt"

"math"

"time"

)

//通道关闭

func fibonacci1(n int, c chan int) {

x, y := 0, 1

for i := 0; i < n; i++ {

c <- x

x, y = y, x+y

}

close(c)

}

//并发

func say(s string) {

for i := 0; i < 10; i++ {

time.Sleep(1000 * time.Millisecond)

fmt.Println(s)

}

}

//两个 goroutine 来计算数字之和

func Sum(s []int, c chan int) {

sum := 0

for _, v := range s {

sum += v

}

c <- sum // 把 sum 发送到通道 c

}

//Printf 可以格式化输出

//Println 直接输出

//只支持显示类型转换

//type point struct{

// x, y int

//}

//

这种不带声明格式的只能在函数体中出现

g, h := 123, "hello"

//var ( // 这种因式分解关键字的写法一般用于声明全局变量

// a int

// b bool

//)

//

常量可以用len(), cap(), unsafe.Sizeof()函数计算表达式的值。常量表达式中,函数必须是内置函数,否则编译不过

//const (

// c = "abc"

// d = len(c)

// g = unsafe.Sizeof(c)

//)

//

//var e, f = 123, "hello"

// 结构体

type Books struct {

title, author, subject string

book_id int

}

//切片

func printSlice(x []int) {

fmt.Printf("len=%d cap=%d slice=%v\n",len(x),cap(x),x)//切片用%v打印

}

//递归

func fibonacci(n int) int {

if n < 2 {

return n

}

return fibonacci(n-2) + fibonacci(n-1)

}

func jiecheng(n uint64) uint64 {

if n > 0 {

return n * jiecheng(n - 1)

}

return 1

}

//接口

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!")

}

//错误处理

type error interface {

Error() string

}

func sqrt(f float64) (float64, error) {

if f < 0 {

return 0, errors.New("sqrt root of negative number")

}

return math.Sqrt(f), nil

}

func main() {

//fmt.Println("Hello, World!")

//fmt.Println("菜鸟教程:runoob.com")

//fmt.Println("Google" + " Runoob")

//

变量声明

//var stockcode = 123

//var enddate="2022-04-07"

//var url= "Code=%d&endDate=%s"

//var strUrl = fmt.Sprintf(url, stockcode, enddate)

//fmt.Println(strUrl)

//

常量 常量中的数据类型只可以是布尔型、数字型(整数型、浮点型和复数)和字符串型。

//const name, age = "laven", 30

//s := fmt.Sprintf("%s is %d years old\n", name,age)

//fmt.Println(s)

//io.WriteString(os.Stdout, s)//需要导入上边io os库

使用内置函数

//println(c, d, g)

//

默认值

//var i int

//var f float64

//var b bool

//var s string

//fmt.Println(i, f, b, s)//默认和别的没啥区别

//

/各自声明

//var b0 bool = true

//var b1 uint8 = 254

//var b2, b3 string = "256", "lisi"

//

var intVal int

//intVal :=1 // 这时候会产生编译错误,因为 intVal 已经声明,不需要重新声明 no new variables on left side of :=

//b4 := 15//根据值自行判定变量类型。

//fmt.Println(b0,b1,b2,b3, intVal, b4, a, b, e, f) //b declared and not used

//iota,特殊常量,可以认为是一个可以被编译器修改的常量。

//iota 在 const关键字出现时将被重置为 0(const 内部的第一行之前),const 中每新增一行常量声明将使 iota 计数一次

struct

//p := point{1, 2}

//fmt.Printf("%v\n", p)//不能用println

//fmt.Printf("%#v\n", p)

运算符

//g := true

//h := false

b2 := g && h

//if g && h {//if else 格式比较固定, 加不加括号都行

// fmt.Println("true")

//} else {

// fmt.Println("false")

//}

//if (!(g && h)) {

// fmt.Println("false")

//}

//a := 10

//if a < 20 {

// fmt.Printf("a 小于 20\n" )

//}

常规位运算

//a := 60

//b := 13

//fmt.Println(a&b)

//fmt.Println(a|b)

//fmt.Println(a >> 1)

//fmt.Println(b << 1)

switch 默认情况下 case 最后自带 break 语句,匹配成功后就不会执行其他 case

如果我们需要执行后面的 case,可以使用 fallthrough

//var grade string = "B"

//marks := 90

//switch marks {

// case 90: grade = "A"

// case 80: grade = "B"

//default:

// grade = "C"

//}

//switch {//可以不加任何变量,相当于true false

// case grade == "A":

// fmt.Println("优秀")

// //fallthrough

// case grade == "B":

// fmt.Println("良好")

// //fallthrough

//default:

// fmt.Println("一般")

//}

//

//a := 3

//switch a {

//case 1,2,3,4: //支持多条件匹配

// fmt.Printf("case a %d\n", a)//Printf 格式化输出

//default:

// fmt.Println("default a %d", a) //Println 不能格式化输出

//}

//循环语句,不需要加括号

//sum := 0

//for i := 0; i <= 10; i++ {

// sum +=i

//}

//fmt.Println(sum)

//sum := 0

//for {//死循环

// sum +=1

//}

//fmt.Println(sum)

//for true {

// println("死循环")

//}

//str := []string{"zhang", "san", "li", "si"}

//for i, s := range str {

// fmt.Println(i, s)

//}

//num := [6]int{1,2,3,4,5}

//for i, s := range num {

// fmt.Println(i, s)

//}

数组

//n := [10]int{}

//var i, j int

//for i = 0; i < 10; i++ {

// n[i] = i + 100

//}

//for j = 0; j < 10; j++ {

// fmt.Println(n[j])

//}

map集合

//countryMap := make(map[string]string)

//countryMap [ "France" ] = "巴黎"

//countryMap [ "Italy" ] = "罗马"

//countryMap [ "Japan" ] = "东京"

//countryMap [ "India " ] = "新德里"

//for country := range countryMap { //获取的相当于index,实际是key, 默认获取index

// fmt.Println(country, countryMap[country])

//}

集合是否存在

//capital, ok := countryMap [ "India "]

//if ok {

// fmt.Println("India 首都:", capital)

//} else {

// fmt.Println("India 首都不存在")

//}

//delete(countryMap, "India ")

//fmt.Println("删除India")

//for country1 := range countryMap { //获取的相当于index,实际是key

// fmt.Println(country1, countryMap[country1])

//}

//for _, capital1 := range countryMap {//不获取index,直接获取值

// fmt.Println(capital1)

//}

///* 定义局部变量 质数或者素数*/

//var i, j int

//for i=2; i < 100; i++ {

// for j=2; j <= (i/j); j++ {

// if(i%j==0) {

// break; // 如果发现因子,则不是素数

// }

// }

// if(j > (i/j)) {

// fmt.Printf("%d 是素数\n", i);

// }

//}

range也可以用来枚举 Unicode 字符串。第一个参数是字符的索引,第二个是字符(Unicode的值)本身。

//for i, c := range "Bingo\a" {

// fmt.Println(i, c)

//}

结构体

//book := Books{"Go 语言", "www.runoob.com", "Go 语言教程", 6495407}

//book1 := Books{title: "Go 语言", author: "www.runoob.com", subject: "Go 语言教程", book_id: 6495407}

//var book2 Books

//book2.title = "c++"

//var book3 *Books

book3 = &book//不同于C++ 好像不能创建

panic: runtime error: invalid memory address or nil pointer dereference

[signal SIGSEGV: segmentation violation code=0x1 addr=0x0 pc=0x47e3cf]

//book3.title ="1689"//不同于C++ 指针用的还是. 必须有前边一行,不然会段错误

//book3.book_id =168

//fmt.Println(book)

//fmt.Println(book1)

//fmt.Println(book2) 忽略的字段为 0 或 空 {c++ 0}

//fmt.Println(*book3)

指针

//a := 20

//var ip * int

//ip = &a

//fmt.Printf("a 变量的地址是: 0x%x\n", &a )

///* 指针变量的存储地址 */

//fmt.Printf("ip 变量储存的指针地址: 0x%x\n", ip )

///* 使用指针访问值 */

//fmt.Printf("*ip 变量的值: %d\n", *ip )

//

nil 指针也称为空指针。

nil在概念上和其它语言的null、None、nil、NULL一样,都指代零值或空值。

//var ptr * int

//fmt.Printf("ptr %x", ptr)//0

//if(ptr != nil) {fmt.Println(" 非空")}

//if(ptr == nil) {fmt.Println(" 空")}

与数组相比切片的长度是不固定的,可以追加元素,在追加时可能使切片的容量增大

可以理解成数组不指定长度

定义

var identifier []type

slice1 := make([]type, len)

make([]T, length, capacity)

初始化 通过内置函数 make() 初始化切片s,[]int 标识为其元素类型为 int 的切片

s :=[] int {1,2,3 }

s := arr[startIndex:endIndex]

//var nums = make([]int, 3, 5)

//printSlice(nums) //len=3 cap=5 slice=[0 0 0]

///* 创建切片 */

//numbers := []int{0,1,2,3,4,5,6,7,8}

//printSlice(numbers)

///* 打印原始切片 */

//fmt.Println("numbers ==", numbers)

///* 打印子切片从索引1(包含) 到索引4(不包含) 左闭右开*/

//fmt.Println("numbers[1:4] ==", numbers[1:4])

///* 默认下限为 0*/

//fmt.Println("numbers[:3] ==", numbers[:3])

///* 默认上限为 len(s)*/

//fmt.Println("numbers[4:] ==", numbers[4:])

//numbers1 := make([]int,0,5)

//printSlice(numbers1)

///* 打印子切片从索引 0(包含) 到索引 2(不包含) */

//number2 := numbers[:2]

//printSlice(number2)

///* 打印子切片从索引 2(包含) 到索引 5(不包含) */

//number3 := numbers[2:5]

//printSlice(number3)

append copy

//var numbers []int

//printSlice(numbers)

///* 允许追加空切片 */

//numbers = append(numbers, 0)

//printSlice(numbers)

///* 向切片添加一个元素 */

//numbers = append(numbers, 1)

//printSlice(numbers)

///* 同时添加多个元素 */

//numbers = append(numbers, 2,3,4)

//printSlice(numbers)

///* 创建切片 numbers1 是之前切片的两倍容量*/

//numbers1 := make([]int, len(numbers), (cap(numbers))*2)

///* 拷贝 numbers 的内容到 numbers1 */

//copy(numbers1,numbers)

//printSlice(numbers1)

//递归

//for i := 1; i <= 10; i++ {

// //fmt.Println(fibonacci(i))

// fmt.Printf("%d ", fibonacci(i))

//}

//阶乘

//var i uint64 = 15

//fmt.Println(jiecheng(i))

//

// //接口

// var phone Phone

// phone = new(NokiaPhone)

// phone.call()

// phone = new(IPhone)

// phone.call()

错误处理

result, err := sqrt(-1) //传递的一个负数,然后就得到了non-nil的error对象

//result, err := sqrt(1.44)

//if err != nil {

// fmt.Println(err)

//} else {

// fmt.Println(result)

//}

类似线程

并发 Go 允许使用 go 语句开启一个新的运行期线程, 即 goroutine,以一个不同的、新创建的 goroutine 来执行一个函数。 同一个程序中的所有 goroutine 共享同一个地址空间。

//go say("hello")

//say("world")

//通道(channel)是用来传递数据的一个数据结构。

//通道可用于两个 goroutine 之间通过传递一个指定类型的值来同步运行和通讯。操作符 <- 用于指定通道的方向,发送或接收。如果未指定方向,则为双向通道。

//默认情况下,通道是不带缓冲区的。发送端发送数据,同时必须有接收端相应的接收数据

//ch <- v // 把 v 发送到通道 ch

//v := <-ch // 从 ch 接收数据 并把值赋给 v

两个 goroutine 来计算数字之和,不加缓冲区的

// 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

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

//如果通道不带缓冲,发送方会阻塞直到接收方从通道中接收了值。

//如果通道带缓冲,发送方则会阻塞直到发送的值被拷贝到缓冲区内;

//如果缓冲区已满,则意味着需要等待直到某个接收方获取到一个值。

//接收方在有值可以接收之前会一直阻塞。

// 缓冲区大小为2

//ch := make(chan int, 2)

//ch <- 1

//ch <- 2

ch <- 3

ch <- 3 //只能塞2个,塞多了就会 fatal error: all goroutines are asleep - deadlock!

fmt.Println(<-ch)

//fmt.Println(<-ch)

//fmt.Println(<-ch)

for {

fmt.Println(<-ch)

}

//c := make(chan int, 10)

//go fibonacci1(cap(c), c)

range 函数遍历每个从通道接收到的数据,因为 c 在发送完 10 个

数据之后就关闭了通道,所以这里我们 range 函数在接收到 10 个数据

之后就结束了。如果上面的 c 通道不关闭,那么 range 函数就不

会结束,从而在接收第 11 个数据的时候就阻塞了,报错 fatal error: all goroutines are asleep - deadlock!

//for i := range c {

// fmt.Printf("%d ", i)

//}

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值