【Golang】一文学完 Golang 基本语法

简介: 【Golang】一文学完 Golang 基本语法

Golang 下载

安装包链接:https://share.weiyun.com/InsZoHHu

IDE 下载:https://www.jetbrains.com/go/

第一个 golang 程序

package main
import "fmt"
func main() {
   fmt.Println("hello golang")
}

每个可执行代码都必须包含 Package、import 以及 function 这三个要素。

变量

主函数文件:

package main
import (
   "awesomeProject/package1"
   "fmt"
)
// 全局变量
var gStr string
var gInt int
func main() {
   // 局部变量
   var lStr string
   var lInt int
   gStr = "out"
   gInt = 100
   lStr = "in"
   lInt = 50
   fmt.Println(gStr)
   fmt.Println(gInt)
   fmt.Println(lStr)
   fmt.Println(lInt)
   // 包外函数
   package1.Fun()
   // 包外变量
   package1.Str = "good"
   fmt.Println(package1.Str)
}

package1 包的文件:

package package1
import (
   "fmt"
)
var Str string
func Fun() {
   fmt.Println("test")
}

注意:golang是以首字母大小写来区分对包外是否可见。

所以 Fun() 函数,Str,想要在 main 文件被访问,都首字母大写了。

数组,切片,字典

package main
import "fmt"
func main() {
   //数组初始化
   var strAry = [10]string{"aa", "bb", "cc", "dd", "ee"}
   //切片初始化
   var sliceAry = make([]string, 0)
   sliceAry = strAry[1:3]
   //字典初始化
   var dic = map[string]int{
      "apple":      1,
      "watermelon": 2,
   }
   // %v 是按照默认格式输出
   fmt.Printf("strAry %+v\n", strAry)
   fmt.Printf("sliceAry %+v\n", sliceAry)
   fmt.Printf("dic %+v\n", dic)
}

切片通过索引的方式指向了数组。切片是可以更改某个元素内容的,数组则不能,在开发中,主要都是使用切片来进行逻辑处理。

条件判断语句

package main
import "fmt"
func main() {
   // 可以通过 := 这种方式直接初始化基础变量
   localStr := "case3"
   if localStr == "case3" {
      fmt.Printf("into ture logic\n")
   } else {
      fmt.Printf("into false logic\n")
   }
   //字典初始化
   var dic = map[string]int{
      "apple":      1,
      "watermelon": 2,
   }
   // 用于检查字典中某个键是否存在,如果存在 num 取键值,ok 取 true,反之 ok 取 false
   if num, ok := dic["orange"]; ok {
      fmt.Printf("orange num %d\n", num)
   }
   if num, ok := dic["watermelon"]; ok {
      fmt.Printf("watermelon num %d\n", num)
   }
   switch localStr {
   case "case1":
      fmt.Println("case1")
   case "case2":
      fmt.Println("case2")
   case "case3":
      fmt.Println("case3")
   default:
      fmt.Println("default")
   }
}

循环

package main
import "fmt"
func main() {
   for i := 0; i < 5; i++ {
      fmt.Printf("i = %d ", i)
   }
   fmt.Println("")
   j := 0
   for {
      if j == 5 {
         break
      }
      fmt.Printf("j = %d ", j)
      j++
   }
   fmt.Println("")
   // 可以指定初始个数也
   var strAry = []string{"aa", "bb", "cc", "dd", "ee"}
   //切片初始化
   var sliceAry = make([]string, 0)
   sliceAry = strAry[1:3]
   for i, str := range sliceAry {
      fmt.Printf("slice i %d, str %s ", i, str)
   }
   fmt.Println("")
   //字典初始化
   var dic = map[string]int{
      "apple":      1,
      "watermelon": 2,
   }
   for k, v := range dic {
      fmt.Printf("key %s, value %d\n", k, v)
   }
}

range 关键字用于迭代切片、数组、字典等可迭代的数据结构。

协程

package main
import (
   "fmt"
   "time"
)
func a() {
   time.Sleep(3 * time.Second)
   fmt.Println("it's a")
}
func b() {
   time.Sleep(2 * time.Second)
   fmt.Println("it's b")
}
func c() {
   time.Sleep(1 * time.Second)
   fmt.Println("it's c")
}
func main() {
   go a()
   go b()
   go c()
   time.Sleep(5 * time.Second)
}

只要使用关键字 go 就能让 a,b,c 三个函数并发运行。

通道(channel)

通道的要点:

1.类似 Linux 中管道(pipe),先进先出; 2.线程安全,多个 goroutine 同时访问,不需要加锁; 3.channel 是有类型的,一个整数的 channel 只能存放整数。

通道的定义:

var ch0 chan int
var ch1 chan string
var ch2 chan map[string]string
type stu struct{}
var ch3 chan stu
var ch4 chan *stu

通道可以用于协程之间数据的传递,一般分为有缓冲通道无缓冲通道

两个协程间如果有数据交流,这时候就可以用通道来传递。

package main
import (
   "fmt"
   "time"
)
var ch chan int
func a() {
   time.Sleep(3 * time.Second)
   a := 5
   ch <- a // 发送操作
   fmt.Println("out of a")
}
func b() {
   time.Sleep(1 * time.Second)
   fromA := <-ch // 接收操作
   b := fromA + 3
   fmt.Println("b is ", b)
}
func main() {
   ch = make(chan int, 1)
   go a()
   go b()
   time.Sleep(20 * time.Second)
   fmt.Println("out of main")
}
  1. make(chan int, 1) 用于创建一个新的信道,其中 chan int 表示该信道用于传输整数类型的值。
  2. 逗号后的 1 是指定信道的缓冲大小。缓冲大小表示信道可以同时容纳的元素个数。 在这种情况下,ch 是一个缓冲大小为 1 的信道,即最多可以同时容纳一个整数值。

举个例子:

创建缓冲信道时,当发送操作(ch <- value)发生时,如果缓冲区已满,发送操作将被阻塞,直到有接收操作(value = <-ch)从缓冲区中读取值。类似地,当接收操作(value = <-ch)发生时,如果缓冲区为空,接收操作将被阻塞,直到有发送操作(ch <- value)将值放入缓冲区。

chSync := make(chan int)    // 无缓冲
chAsyn := make(chan int, 1) // 有缓冲

理解有缓冲和无缓冲:

同样是向通道里塞一个数据:chSync <-1 无缓冲场景:一直要等有别的协程通过<-chSync接手了这个参数,那么chSync<-1才会继续下去,要不然就一直阻塞着。 有缓冲场景:chAsyn<-1则不会阻塞,因为缓冲大小是1,只有当放第二个值的时候,第一个还没被人拿走,这时候才会阻塞。 仔细理解下,实际这就是同步和异步的区别,无缓冲一定是同步等待,有缓冲只有在缓冲满了,异步又处理不过来的时候,才会阻塞。

举个例子:

无缓冲

package main
import (
   "fmt"
   "time"
)
var ch chan int
func a() {
   time.Sleep(3 * time.Second)
   a := 5
   ch <- a
   fmt.Println("out of a")
}
func b() {
   time.Sleep(1 * time.Second)
}
func main() {
   ch = make(chan int) // 无缓冲管道
   go a()
   go b()
   time.Sleep(20 * time.Second)
   fmt.Println("out of main")
}

输出:

out of main

有缓冲:

package main
import (
   "fmt"
   "time"
)
var ch chan int
func a() {
   time.Sleep(3 * time.Second)
   a := 5
   ch <- a
   fmt.Println("out of a")
}
func b() {
   time.Sleep(1 * time.Second)
}
func main() {
   ch = make(chan int, 1) // 有缓冲管道
   go a()
   go b()
   time.Sleep(20 * time.Second)
   fmt.Println("out of main")
}

输出:

out of a
out of main

接口

package main
import "fmt"
// Shape 是接口
type Shape interface {
   Area() float64
   Perimeter() float64
}
type Rect struct {
   height float64
   weight float64
}
func (p *Rect) Area() float64 {
   return p.height * p.weight
}
func (p *Rect) Perimeter() float64 {
   return 2 * (p.height + p.weight)
}
func main() {
   var s Shape = &Rect{height: 10, weight: 8}
   fmt.Println(s.Area())
   fmt.Println(s.Perimeter())
}

代码中Shape就是一个接口,声明了两个方法:面积(Area)和周长(Perimeter)。 咱们定义了一个具体结构 Rect,实现这个接口。可以看到,用基础的 Shape 接口,可以一个指向 Rect 对象,并调用其方法。

Golang 只需要实现某个 interface 的全部方法,那么就是实现了该类型。所以,Golang的继承关系是非侵入式的,这也是Golang的特色与优点。

webserver

用 http 裸写:

package main
import (
   "log"
   "net/http"
)
func SayHello(w http.ResponseWriter, r *http.Request) {
   w.Write([]byte("hello")) // 以字符串"hello"作为返回包
}
func main() {
   http.HandleFunc("/say_hello", SayHello)
   err := http.ListenAndServe(":8080", nil) // 开启一个http服务
   if err != nil {
      log.Print("ListenAndServe: ", err)
      return
   }
}

运行,然后就能访问了:http://localhost:8080/say_hello

写在最后:

以上就是本篇文章的内容了,感谢你的阅读。

如果感到有所收获的话可以给博主点一个赞哦。

如果文章内容有遗漏或者错误的地方欢迎私信博主或者在评论区指出~

相关文章
|
8月前
|
Go
4.1 golang基础语法
4.1 golang基础语法
53 0
|
3月前
|
安全 Java Go
【Golang入门】简介与基本语法学习
Golang语言入门教程,介绍了Go语言的简介、基本语法、程序结构、变量和常量、控制结构、函数、并发编程、接口和类型、导入包、作用域以及错误处理等关键概念,为初学者提供了一个全面的学习起点。
62 0
|
5月前
|
Go 开发者 索引
Golang 中 for 循环的语法详解
【8月更文挑战第31天】
40 0
|
8月前
|
Go
Golang深入浅出之-Go语言基础语法:变量声明与赋值
【4月更文挑战第20天】本文介绍了Go语言中变量声明与赋值的基础知识,包括使用`var`关键字和简短声明`:=`的方式,以及多变量声明与赋值。强调了变量作用域、遮蔽、初始化与零值的重要性,并提醒读者注意类型推断时的一致性。了解这些概念有助于避免常见错误,提高编程技能和面试表现。
93 0
|
8月前
|
JSON 安全 Java
golang面试:golang基础语法(一)
golang面试:golang基础语法(一)
72 0
|
存储 人工智能 Java
深入了解Golang:基本语法与核心特性解析
深入了解Golang:基本语法与核心特性解析
|
Go
Golang语法入门指南
Go是一种现代、高效、并发的编程语言,被设计用于构建可靠且高性能的软件。它具有简单的语法和强大的标准库,适用于各种类型的应用程序开发。本博客将引导您快速入门Golang的基本语法,并提供一些实用的技巧和最佳实践。
97 0
|
存储 关系型数据库 MySQL
Golang基本语法-掘金课程笔记
Golang基本语法-掘金课程笔记
136 0
Golang基本语法-掘金课程笔记
|
编译器 Go
Golang泛型语法
在定义函数(结构等)时候,可能会有多种类型传入。只有在真正使用才知道是什么类型,此时就可以用一个更加宽泛的类型(必须存在一定约束,只能在那些类型的范围内使用)暂时占位。这个类型就叫泛型
849 0
|
存储 Java Go
一起学Golang系列(四)学习Go语言语法,这篇文章就够了!
前面已经了 Go 环境的配置和初学Go时,容易遇到的坑。我们知道Go语言和我们以前的Java或是C#哈时候很大差别的。所以在学习Go,首先必须要熟悉Go语言的基础语法。接下来就为初学者大致介绍下Go语言基础语法。
一起学Golang系列(四)学习Go语言语法,这篇文章就够了!