Go语言基础语法

Go语言基础语法

注释

我们为什么写注释?

一个项目,是很多组成的。写的时候,你能看懂的。 半年、一年 (时间久了,自己写代码看不懂了)

对接、项目很多时候都是多人协作完成。(很难沟通,直接读懂代码是比较困难)

什么是注释: 来描述我当前这个代码是做什么的,或者一些批注

package main

import "fmt"

// 注释是不会被程序执行的

// // 单行注释
// 注释主要是针对一些自己不太理解的业务,或者复杂的业务。开源项目中,注释十分完善。

/* 多行注释
。。。。。。
写自己的理解和当前代码作用
*/
func main() {
	
	fmt.Println("Hello,World!")

}

以helloworld为例:

// 代表是main包,下面如果存在 main 函数,那么就是程序的入口
package main

// 导入了一个 fmt 包,可以通过它来调用打印函数、输出一行话....
import "fmt"

// main函数  func 函数  main 函数的名字 () 没有参数
func main() {
   // 打印了一句helloworld
   fmt.Println("Hello,World!")

}

写注释是一个十分良好的习惯,我们都应该按照要求给自己代码写好注释,为了自己,也为了他人。很多大公司里也是对注释有严格要求的。

变量

变量的定义

程序 : 我们向电脑说了一段话,需要电脑才能理解 (沟通机制 ,xxx语言 – 汇编 – 机器码)

电脑实际上识别的是机器码 : 0 1 1 1 0 1 (高低电频)

机器码 : 穿孔纸带

汇编:早些时候,现在的很多机器硬件底层代码,都是汇编

人能读懂的代码:英文、中文

将我们的语言和机器进行对接 (C、Java、Go —> 编译器 --> 计算机中去执行:无需理解的,我们只需要写我们能看懂的代码即可 )

我们理解的世界、和计算机的世界要一一对应:

定义:一切都是需要去定义的。

计算机也需要去定义一些东西。

人名: 名字 name = Night

名字(变量)

name = 张三

name = 李四

计算机也需要这样来认识我们写的代码,也需要一个格式

通过 var 关键字来定义变量

变量名字 需要告诉计算机这个信息(变量)是什么类型的,数据类型:数字、字符串、小数… = “变量的值”

//用程序描述一个人的信息
// string 字符串类型
var name string = "Night"
// int 数字类型
var age int = 27

var sex string = "男"

// Java
String name = "Night"

**公式:定义变量 var 变量名 变量类型 **

package main

import "fmt"

func main() {
   // var 变量名 变量类型
   // 定义变量 ,如果没有给这个变量赋值, 就是这个数据类型的默认值。
   // string 默认值 ”“  int 默认值 0
   var name string
   var age int

   // 可以同时定义多个变量,也只需要使用 var() 关键字
   var (
      addr  string
      phone int
   )

   // goland 快捷键 : 复制当前行到下一行  Ctrl + D
   fmt.Println(name)
   fmt.Println(age)
   fmt.Println(addr)
   fmt.Println(phone)

   // 变量的使用,在定义完毕变量之后直接可以操作这个变量
   // 给变量赋值 ,符号  = 赋值(不能叫等于)
   // 将 "秦疆" 赋值 给 name 这个变量。
   name = "秦疆"
   // 使用变量,直接打印或者进行一些操作都可以
   fmt.Println(name)

   // 变量是可以被重复赋值的,变量。
   name = "张三"
   fmt.Println(name)

   // 在定义变量的时候直接进行赋值。
   var dog string = "旺财"
   fmt.Println(dog)

}

短变量的申明方式(语法糖,方便开发人员开发)

package main

import "fmt"

func main() {

   // 只定义变量,不使用可以吗. 理论可以,实际在Go语言中不行。
   // 无意义代码,报错!

   // 问题1 :能不能不写数据类型
   // 问题2 :不用var 直接定义变量呢?

   // 自动推导,一个短变量声明
   name := "Night"
   age := 18
   // 语法糖(偷懒,简化开发!)
   // := 相当于快递定义变量。如果给这个变量赋值了,那么会自动推导它的类型
   // var 、 数据类型的定义都被省略的。
   // 数据类型 go语言中基本的数据类型。

   fmt.Println(name)
   fmt.Println(age)

   // 定义了变量name2
   var name2 string
   // 在快速声明中,如果 := 左边的变量已经存在了,那么它将无法创建,无法重新定义
   name3 := "zuoyi444"
   fmt.Println(name2)
   fmt.Println(name3)
   name3 = "zhangsan666"
}

小结

1、定义变量使用定式 var 变量名称 变量数据类型

2、给变量赋值 。 定义的时候直接赋值、 通过变量名来赋值、

3、语法糖 := 。 可以通过它来快速定义变量,如果是基本数据类型,字符串、数字,它会自动推导类型

所谓的基础语法,所有的编程语言大同小异。

变量的交换

在这里插入图片描述

package main

import "fmt"

func main() {
   /* 在编程中遇到的第一个问题:变量交换
   var a int = 100
   var b int = 200

   var t int
   t = a
   a = b
   b = t
   */
   // 在Go语言中,程序变量交换,也有语法糖
   var a int = 100
   var b int = 200
   // fmt.Println 可以传递多个参数,用逗号隔开,直接打印
   fmt.Println("a=", a, ",b=", b)
   // 把a,b赋值给b,a  语法糖, 底层本质还是用到了临时变量。简化我们的开发
   b, a = a, b
   fmt.Println("交换后 a=", a, ",b=", b)
   
   // 复杂的问题都给我们简单化了,我们开发很轻松,编译器帮我们在底层处理。
}

理解变量(内存地址)

在这里插入图片描述

package main

import "fmt"

func main() {
   // 变量到底是个什么玩意?
   // num 实际上是一片内存空间
   // 我们想要看一个变量的内存地址,只需要在变量名前加上 & 即可。
   // 取地址符 (指针)
   var num int
   num = 1000
   // 思考:这个num在计算机中是什么样子的。 num
   fmt.Printf("num的值:%d,内存地址:%p\n", num, &num)
   num = 2000
   fmt.Printf("num的值:%d,内存地址:%p\n", num, &num)

   // 汇编。理解一切

   var name string
   name = "张三"
   // 思考:这个num在计算机中是什么样子的。 num
   fmt.Printf("num的值:%s,内存地址:%p\n", name, &name)
   name = "李四"
   fmt.Printf("num的值:%s,内存地址:%p\n", name, &name)

   // 打印内存地址的方式之一。 Print  f格式化输出
   // 内存
   // 第一个参数 输出字符串
   // % 占位符。
   // 占位符的数量,要和后面待输出的数量一直
   // %d 数字 int d
   // %p 内存地址,num需要取出变量的地址。
   // %s 字符串。
   // \n 换行
   //fmt.Printf("num的值:%d",num)
}

匿名变量

package main

import "fmt"

// 变量 ( 有名字、没有名字:匿名 )
// 十分特殊、匿名变量 (黑洞,一切东西丢进去,任何赋值给匿名变量的值都会被丢弃)
// _ 下划线,就是匿名变量在Go语言中

// 函数 一段代码的集合。
//
// func  test 函数名 (参数,参数....) 返回一些东西{
//  一段代码的集合,通过or不通过参数,返回结果
// }
//
// 基本的操作函数,调用函数,返回两个数字。
func test() (int, int) {
   // return 返回结果
   return 100, 200
}

// 在Go语言中会大量使用到
// 匿名变量不占用内存空间,不会分配内存。
func main() {
   // 调用这个test函数,应该会返回两个结果,100,200

   // 变量 : 除了直接定义之外,还可以是一个结果的赋值
   //var a int = 100
   // 只想要test返回的第一个结果,这时候就需要使用匿名变量 _。
   a, _ := test() // a,b := 100,200
   fmt.Println(a)
   // 只想要test返回的第二个结果,这时候就需要使用匿名变量 _。
   _, b := test()
   fmt.Println(b)
}

变量的作用域

package main

import "fmt"

// 全局变量:在当前go文件中生效...
// 定义在go文件非函数内,在package和import下面
// 全局变量的定义必须使用 var 关键字, 如果直接使用 := 则无法创建该变量
// 全局变量和局部变量是可以重名的,优先级。到底用谁
var c int

func main() {
   // 局部变量:只在一定的范围内生效...
   // 在函数体内声明变量
   var a int = 3
   var b int = 4
   // 如果全局变量有,那么直接使用全局变量来接收。
   c = a + b
   fmt.Printf("a=%d,b=%d,c=%d\n", a, b, c)
   fmt.Printf("c内存地址:%p\n", &c)
   b = 1
   // 但是如果在局部有和全局同名的变量,优先使用局部变量
   c := a + b
   fmt.Printf("a=%d,b=%d,c=%d\n", a, b, c)
   fmt.Printf("c内存地址:%p\n", &c)
   b = 5
   // 就近原则
   c = a + b
   fmt.Printf("a=%d,b=%d,c=%d\n", a, b, c)
   fmt.Printf("c内存地址:%p\n", &c)

   // Printf 格式化输出 (参数一:需要打印的内容,%是占位符,通过后续参数给他一一赋值)
   fmt.Printf("a=%d,b=%d,c=%d\n", a, b, c)
}

就近原则

package main

import "fmt"

// Go语言程序中全局变量与局部变量名称可以相同,但是函数体内的局部变量会被优先考虑。
// string  int   float64  浮点数(小数)
var a float64 = 3.14

func main() {
   var a float64 = 2.18
   fmt.Println(a)
}

常量

常量: 不能变化的量。 这个变量是一个特殊的变量,无法改变的。 关键字 const

两个区别:变量的定义使用 var 、常量的定义是使用const

是什么机制导致他无法改变的?

Go语言底层的约定,实际上它是可以改变的,需要跳过常量名,直接找到内存地址,进行修改值。

package main

import "fmt"

// 常量和变量放置的内存地址不同  (栈、堆、常量池)
// 程序正常执行,压栈

// 常量
func main() {
   // 规定:建议这么去做
   // 我们通过定义常量的时候,建议大家使用大写字母来定义。区分与普通变量
   // 一旦定义之后是不会发生变化的。
   // 定义格式  const 常量名[type] = value
   const URL string = "https://blog.csdn.net/qq_45371023"

   // 隐式定义 常量的自动推导是可以省略一些基础类型,
   const URL2 = "www.baidu.com"

   // 可以同时定义多个常量
   const URL3, URL4 string = "https://blog.csdn.net/qq_45371023", "www.baidu.com"

   //
   fmt.Println(URL)
   fmt.Println(URL2)
   fmt.Println(URL3)
   fmt.Println(URL4)

   // 在我们真实的世界也是有很多不会发生变化量,那在程序中对应的就是常量
   const PI = 3.14
   // 固定的东西,都建议统一定义成常量。
   const LENGTH int = 8000
   const WIDTH int = 8000

   // 常量是无法被修改的。
   //LENGTH = 13

   fmt.Println(LENGTH)

}

特殊的常量 iota

package main

import "fmt"

// 特殊的常量 iota 常量计数器,const (多个常量,自动帮我们 + 1)
func main() {
   // iota 每次定义新的常量,在一组 const 中,那么它会自动 + 1
   // iota 默认值0,
   const (
      a = iota
      b = iota
      c = iota
      d = 0
      e = iota
      // 如果在定义 const 的时候,如果下面的常量没有赋值,默认沿用上面一个常量定义的赋值。
      f
      g
      h = iota
      // ... 1000+
   )
   const (
      i = iota // 0
      j = 0    // j =0  iota + 1 = 1
      k = iota // iota + 1 = 2
   )
   // 0 1 2  d=0 ,e = 4
   fmt.Println(a, b, c, d, e, f, g, h)
   fmt.Println(i, j, k)

}

变量的定义 : var 变量名 type(数据类型)

字符串 string

数字整数 int

小数 浮点数 float64 / float32

数据类型

动态类型编程语言

  • 运行时判断

静态类型的编程语言 : Go 、C 、

  • 在开发的时候,就需要给一些定义的变量赋值空间大小。C 需要自己去开辟这个空间

数据类型 : 每种在Go语言中出现的基本数据类型,会有一个默认的空间大小。
在这里插入图片描述

布尔数据类型

布尔型的值只可以是常量 true 或者 false。一个简单的例子:var b bool = true。

package main

import "fmt"

func main() {
   // bool类型,只有两个值 true 和 false。  对和错
   // 定义变量  bool 布尔类型的定义 与 int、string 都是Go语言中基本数据类型。
   var b1 bool
   var b2 bool

   b1 = true
   b2 = false
   // f 格式化输出  %d 整数  %s 字符串 %p内存地址  %T 类型 %t bool值
   fmt.Printf("b1=%T,%t\n", b1, b1)
   fmt.Printf("b2=%T,%t\n", b2, b2)

   // 比大小
   var a int = 1
   var b int = 2
   // 如果  xxx  否则 xxx
   // 结果就是bool类型
   fmt.Println(a > b)
   if a > b {
      fmt.Println("a是大于b的")
      // .....
   } else {
      fmt.Println("a是小于b的")
   }

   // bool 类型的默认值 false, 规定  false  0   true = 1
   var b3 bool
   fmt.Println("bool默认值:", b3)

}

数字型 int

整型 int 和浮点型 float32、float64,Go 语言支持整型和浮点型数字,并且支持复数,其中位的运算采用补码。

Go 也有基于架构的类型,例如:uint 无符号、int 有符号

每个数字,都是有范围的, 有的数字只能大于0

有的数字可以小于0

在计算机中,所有的东西最终都是存在内存当中的,所以我们不能无限的放置东西(数字)

序号类型和描述
1uint8 无符号 8 位整型 (0 到 255)
2uint16 无符号 16 位整型 (0 到 65535)
3uint32 无符号 32 位整型 (0 到 4294967295)
4uint64 无符号 64 位整型 (0 到 18446744073709551615)
5int8 有符号 8 位整型 (-128 到 127) 0
6int16 有符号 16 位整型 (-32768 到 32767)
7int32 有符号 32 位整型 (-2147483648 到 2147483647)
8int64 有符号 64 位整型 (-9223372036854775808 到 9223372036854775807)

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-EeTm9PYE-1676377267750)(Go语言基础语法.assets/image-20230205202823463.png)]

1、有符号数和无符号数的区别

  • 0为分解,正负推进…空间大小 ,空间大小是根据位来判断的 int 8 16 32 64、二进制的位,这个数据类型值的上限
  • 0 + 空间大小

2、了解 二进制基本原理

3、尝试自己推算出每个整数数据类型的大小上限值。

浮点型

浮点数 float :float32 float64 ,也是一个空间的大小。

package main

import "fmt"

// 浮点数 float ,默认是 float64 ,32
func main() {
   // 浮点数是不精确的,计算机底层导致的 0 1、浮点数、复数,没办法做到精确计算
   var f1 float64
   f1 = 3.16
   var f2 float32
   f2 = 5
   fmt.Println(f1)
   // // 默认的 float 类型,都是保留了6位小数
   // 浮点数的格式化输出 %f ,都是保留了6位小数,保留2位或者3位怎么实现
   // .3 保留3位小数 其余类推
   // 如果小于了当前保留的位数,四舍五入
   fmt.Printf("%T,%.1f\n", f1, f1)
   fmt.Printf("%T,%f", f2, f2)

}

验证:浮点数计算时不精确的

package main

import "fmt"

func main() {
   // 浮点数 ; 符号位  + 指数位 + 尾数位(存储过程中,可能会丢失,造成精度损失)。
   // float64 的空间 > float32
   var num1 float32 = -123.0000901
   var num2 float64 = -123.0000901
   fmt.Println(num1)
   fmt.Println(num2)
   // 结论:
   // 1、使用float来计算,可能导致数据不精确。
   // 2、float64的精度>float32, go语言中,浮点数默认使用的是float64
}

通常情况下,关于浮点数、默认使用 float64 。

特殊的数字类型

package main

import "fmt"

// byte
func main() {
   // 别名uint8是byte,十分常用
   // byte = uint8 (0-255之间的整数,我们通常使用byte来定义) uint8
   var num1 byte = 255
   fmt.Println(num1)
   fmt.Printf("%T\n", num1)

   // 不经常用 rune int32
   var num2 rune = 1000000000
   fmt.Println(num2)
   fmt.Printf("%T\n", num2)

   // int、系统大小来的,32位  32、64默认是64
   // 软件跑在32位系统上是不兼容的
   var num3 int = 100000
   fmt.Println(num3)
   fmt.Printf("%T\n", num3)
}

64位的操作系统是可以兼容32位的、32为不能跑64位的软件。 寻址空间。

字符串类型

字符串就是一串固定长度的字符连接起来的字符序列。 一段中文或者英文 (编码- 字符)

Go语言中,所有的字符串都是由单个 字符 连接起来的。兼容全世界文字的

拓展:了解编码表

UTF-8编码 , 目前兼容我们绝大部分的文字和符号。

GBK编码:中国的编码表,号称兼容所有的中文汉字。

Unicode编码表 :号称兼容了全世界的文字。

编码 中 本质是一个数字

package main

import "fmt"

func main() {

   var str string
   str = "Hello,World"
   fmt.Printf("%T,%s\n", str, str)
   // H E L L O , W O R L D
   // Go语言中,所有的字符串都是由单个 字符 连接起来的。
   // 单引号是字符、双引号才是 string 类型
   // 字符本质是整型
   v1 := 'A'
   v2 := "A"
   fmt.Printf("%T,%d\n", v1, v1)
   fmt.Printf("%T,%s\n", v2, v2)

   v3 := '魑'
   fmt.Printf("%T,%d\n", v3, v3)
}

转义字符

package main

import "fmt"

func main() {
   // 特殊的字符 转义字符 \n
   // \n 换行
   fmt.Println("hello\nworld")
   // \b   backspace  删除上一个字符
   fmt.Println("hello\bworld")
   // \t  Tab
   fmt.Println("hello\tworld")
}

在这里插入图片描述

数据类型的转换

在必要以及可行的情况下,一个类型的值可以被转换成另一种类型的值

由于Go语言不存在隐式类型转换,因此所有的类型转换都必须显式的声明: A = A(B)

package main

import "fmt"

// 类型转换
func main() {
   // 数据类型转换在Go中就一个格式
   // 新类型的值 = 新类型(旧类型的值)

   // 高位向低位转 (int64  int32  int16)
   
   // 浮点数转整数,截断,只保留整数部分
   a := 5.9    // float
   b := int(a) // b 就是int类型的a = 5

   fmt.Printf("%T,%.1f\n", a, a)
   fmt.Printf("%T,%d\n", b, b)

   c := 1
   d := float64(c)
   fmt.Printf("%T,%d\n", c, c)
   fmt.Printf("%T,%f\n", d, d)

   // 布尔类型转换,布尔类型 是不支持类型转换的。
   //var flag bool = true
   //f := int(flag)
   
}

变量的定义: var 变量名 数据类型

数据类型 是没有上限的,以上的都是基本数据类型,常用的,系统自带的,必要的。任何一个编程语言都会有。

除了这些之外,会存在一些自己开发的数据类型(数据结构都是可以自己定义的)

运算符

算术运算符

package main

import "fmt"

func main() {
   // 算术运算符 + - * / % ++ --
   var a int = 7
   var b int = 3
   var c int // 结果
   // 双元运算符,由两个变量参与运算,或者多个
   c = a + b
   fmt.Println(c)
   c = a - b
   fmt.Println(c)
   c = a * b
   fmt.Println(c)

   c = a / b // 除 7/3 = 2...1
   fmt.Println(c)
   c = a % b // 取模 余数  1
   fmt.Println(c)

   // 单元运算符,用自己就可以操作得出结果
   //  自增++  自减--
   fmt.Println(a)
   a++ // a = a + 1 自增,在自己的基础上 + 1
   fmt.Println(a)

   a = 7
   a-- // a = a-1。  遍历输出一些东西(10000个数字)
   fmt.Println(a)
   
}

关系运算符(必须记住)

大于 >

小于 <

等于 ==

不等于 !=

大于等于 > =

小于等于 < =

结果:布尔值 (对或者错)

package main

import "fmt"

func main() {

   var a int = 21
   var b int = 10
   // 关系运算符、和 算术运算符,都是小学4年级学的,必须要掌握
   fmt.Println(a > b)
   fmt.Println(a >= b)
   fmt.Println(a < b)
   fmt.Println(a <= b)
   fmt.Println(a == b)
   fmt.Println(a != b)

}

逻辑运算符(难点)

判断多个条件是否存在的时候,就需要逻辑

&& 与 只要有一个错,大家都是错的 false,两个都对才是对的。 多条件同时满足(与)

与(和) And 对 And 错 对 And 对(true) 错 And 对 错和错 共生!

|| 或 只要有一个对的,那么就是对的,两个都是错的,结果才是错的。(or)

或 Or 或者 对 or 错 (true) 对 or对(true) 错 or对 (true) 错or错 (错)

**!**如果是真的,那么为假,如果是假,则为真。

非(取反)

package main

import "fmt"

// 逻辑运算符,结果也是布尔值。 多个条件判断是否成立作用
func main() {
   var a bool = true
   var b bool = false
   var c bool = true
   var d bool = false

   // 双元运算符  &&   ||

   // 与 都为真结果才为真,如果有假则结果为假
   // 账户名 和 密码 都要正确才可以登录
   fmt.Println(a && b)
   fmt.Println(a && c)
   fmt.Println(a && d)
   // 短路判断, 在这里 4<5 是没有运算的,也不要运算,因为在 3<2 结果已经出现了
   fmt.Println(1 == 1 && 3 < 2 && 4 < 5)
   fmt.Println("=============================")
   // 或 || 只要满足一个条件,整体结果就位 true  or
   // 如果所有条件都不满足,结果为false。
   // 看文章 (登录、缓存、能够访问......)
   fmt.Println(a || b) // true  false
   fmt.Println(a || c) // true  true
   fmt.Println(a || d) // true  false
   fmt.Println(b || d) // false  false

   // 单元运算符  一个条件就够,就是将当前结果的bool置反
   // 如果真,则结果是假,如果假,则结果是真,
   // 取反
   fmt.Println(!(b || d))
   fmt.Println(!true)
   fmt.Println(!!false)
    
   // 
	// 结果是false 
	if !false { //true
		// 执行...
	}

}
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值