go语法入门1

语法基础

注释

// 单行注释
/* xxxx */ 编译器忽略该区间,其间都被认为是注释内容。虽然Go支持,但很少使用,一般都用多行//

//包注释
package main

import "fmt"

/*
x int
y int
*/

// x int
// y int  多行注释

func main() {
	fmt.Println("zzzz")	 //打印
	//TODO: 将来完成,一把是这个任务没写完,加入这个注释,方便下次继续完成这个任务	
}

// TODO: 将来完成,推荐
// NOTE: 请注意
// Deprecated: 告知已经过期,建议不要使用。未来某个版本可能移除
  • 函数、结构体等习惯把注释写在上面
  • 包注释会写在package之上

命名规范

  • 标识符采用CamelCase驼峰命名法
    如果只在包内可用,就采用小驼峰命名
    如果要在包外可见,就采用大驼峰命名

    userName 小驼峰命名  首字母小写中间大写 
    UserName 大驼峰 首字母大写 中间大写   区别在与包外可见
    user_name snake 蛇形命名
    
  • 简单循环变量可以使用i、j、k、v等

    一般用简单的英文单词
    
  • 条件变量、循环变量可以是单个字母或单个单词,Go倾向于使用单个字母。Go建议使用更短小

  • 常量驼峰命名即可
    在其他语言中,常量多使用全大写加下划线的命名方式,Go语言没有这个要求
    对约定俗成的全大写,例如PI

  • 函数/方法的参数、返回值应是单个单词或单个字母

  • 函数可以是多个单词命名

  • 类型可以是多个单词命名

  • 方法由于调用时会绑定类型,所以可以考虑使用单个单词

  • 包以小写单个单词命名,包名应该和导入路径的最后一段路径保持一致

  • 接口优先采用单个单词命名,一般加er后缀。Go语言推荐尽量定义小接口,接口也可以组合

关键字

25个关键字

break     default    	func     interface   select
case      defer      	go        map        struct
chan      else       	goto     package     switch
const     fallthrough   if       range        type
continue  for           import    return    var

标识符

  • 一个名字,本质上是个字符串,用来指代一个值

  • 只能是大小写字母、数字、下划线,也可以是Unicode字符

    Unicode字符也可以是中文 但是不推荐标识符采用中文的字符
    
  • 不能以数字开头

  • 不能是Go语言的关键字

    不能和关键字冲突
    
  • 尽量不要使用“预定义标识符”,否则后果难料

  • 大小写敏感

字面常量

它是值,不是标识符,但本身就是常量,不能被修改。
Go语言中,boolean、rune、integer、float、complex、string都是字面常量。其中,rune、
integer、float、complex常量被称为数值常量。

100
0x6162 0x61_62_63
3.14
3.14e2
3.14E-2

'测'								//字符 ''单引号中  有且仅有一个
'\u6d4b'
'\x31'
'1'
'\n'
"abc" "\x61b\x63"				// 字符串  ""双引号中,可以有一个也可以多个
"测试" "\u6d4b试"
"\n"


true
false
iot

‘1’ "1"的区别

‘1’ 这个代表有且只有一个数字就是1 代表的是字符

“1” 这个代表和这个字符串里有1 代表的是字符串

常量

常量:使用const定义一个标识符,它所对应的值,不允许被修改。
对常量并不要求全大写加下划线的命名规则。

  • 常量必须在定义是赋值,并且后面不能再变化

  • 数组不能赋值给常量

    const 常量名 = 初值 常量必须在定义是直接赋初值
    
    package main
    import "fmt"
    
    func main() {
    	const a int = 100 // 指定类型定义常量并赋值
    	const b = "abc"   // 定义常量,等式左边未给出类型,将进行类型推导
    	const c = 12.3
    	const d = 'T'
    	fmt.Printf("%T\n", a)
    	fmt.Printf("%T\n", b)
    	fmt.Printf("%T\n", c)
    	fmt.Printf("%T\n", d)
    }
    
    int					%T 输出值对应的类型
    string
    float64
    int32
    

    批量定义

    const (
    		c    = "abc" // 类型推导    String类型
    		d    = 100   // 字面常量 无类型常量100 关联, 默认推导int类型
    		e uint8 = 100   // 无类型常量100 ,和左边有类型常量uint8类型 e
    		// int 8bits => 1bytes -128~127 0~255
    		f float32 = 1.5       //flost32类型
    		g         = true     //bool类型
    	)
    

变量

  • 变量:赋值后,可以改变值的标识符。
  • 建议采用驼峰命名法。
package main

import "fmt"

func main() {
	var a // 错误,无法推测类型
	var b int // 正确,只声明,会自动赋为该类型的零值
	var c, d int // 正确,声明连续的同类型变量,可以一并声明,会自动赋为该类型的零值
	var b = 200 // 错误,b多次声明,第二行已经声明过
	b = 200 //正确
	var f, e int = 11, 22 // 正确
}
// 用var声明,立即赋值,或之后赋值
var b int // 正确,只声明,会自动赋为该类型的零值
b = 200
b = 300
b = "4" // 错误,类型错误

var a = 100 // 右边无类型常量,缺省类型是int,左边a没有指定类型,用到类型推导,所以a为int类型 var a int = 100
var a // 错误的,因为没有右边,go是强类型语言,此时不能利用右边来推导,左边又没有指定类型,所以错误
var a int // 正确,指定了类型,但是没有赋值。go中正确的原因是 零值可用。int的零值是0
var a int32 = 200 // 正确,指定了类型,也赋值。不会采用类型推导

// 批量赋值
var a int, b string // 错误,批量不能这么写
var ( // 正确
  a int
  b string
)

var ( // 错误,变量必须有类型,但没有给类型,也不能使用值来推导类型
  a
  b
)

var a int, b string = 111, "abc" // 错误,多种类型不能这么写,语法不对
var (
  a int   = 111
  b string = "abc"
) // 正确,建议批量常量、变量都这么写
var (
  a = 111
  b = "abc"
) // 正确,类型推导

变量:标识符的指向的值建立后,可以改变

  • 类型也可以变,往往动态语言JS、Python,举例 a = 100, a=“abc”, a=[1,2,3]
  • 同类型可以变
  • 批量定义 必须给定类型或者赋值,但是常量可以不用定义类型,因为常量在定义的时候必须给定一个值,因此可以进行类型推到
短格式
a := 100 // 赋值语句,短格式变量定义语句,定义变量。定义了变量标识符a,右边可以用来推导a的类型为int
相当于 var a = 100 同样的 没有定义类型 通过字面量来推导a的类型

不可以重复定义类型

var a int //零值0  
a := 100 //错误的  因为前面已经定义类型了  短格式在定义类型是不允许的	

有特例:

var a int
a,b := 123,"abcd"  //竟然可以?在这里a不能重新定义为新类型,a被检测到了,go语言上只能迁就你了,但是要求a同类型,b是新定义的

短格式要求:

a, b := 123, "abcd"
a, b, c := 123, "abcd", 12.5 // 短格式批量同一行定义,因为短格式不能指定类型,所以采用类型推导,左右要求个数一致

短格式
使用 := 定义变量并立即初始化
只能用在函数中,不能用来定义全局变量
不能提供数据类型,由编译器来推断

交换

go的数据交换是特殊的 具体的特殊就是在定义和赋值后,想相当于对变量名进行了快照的处理,在交换数据时,是直接调用快照前,变量指向的数值

package main

import "fmt"

func main() {
	a := 100
	b := 200
	a, b = b, a  //按照别的语言当a=b时,a=200了,后面的b=a肯定是调用的是a=200,但是go不是,go依旧调用的是前面a=100,相当于是快照了
	fmt.Println(a, b) 

}

[Running] go run "f:\goprpject\test2\m.go"
200 100

iota

//一定是批量定义const这种,如果是单行 iota一直都是0

// iota 定义成批常量,iota从0,从成批的第一行

package main

import (
	"fmt"
)

func main() {
	const (
		a = iota    //第一行为0
		b			// 1	
		c			// 2
	)
	fmt.Println(a, b, c)
}
0 1 2
package main

import (
	"fmt"
)

func main() {
	const (
		a = iota + 1 // 1   
		b            // 2  批量定义的时候,下面一行可以继承上面的表达式 b = iota +1
		c			// c = iota + 1   iota=2  c=3 
		_ // 空白标识符,黑洞 _=iota+1    iota =4
		d      
		t = 100
		_
		_
		e // ? e=100    //批量定义的时候,下面一行可以继承上面的表达式 
	)
	fmt.Println(a, b, c, d, t, e)
}
1 2 3 5 100 100
	const (
		m = 100   // iota:0
		n // n : 100, iota : 1
		a = iota * 2  // 2 * 2
		b = iota * 2  // 3 * 2
		c
		d
	)
	fmt.Println(a, b, c, d) // 4 6 8 10

总结:iota只能用于常量,是在成批定义和序列有关的常量定义,iota在成批定义中,可以认为是行索引,可以应用为日期和月份

索引和序号的区别:序号一般是从1开始的,行索引一般从0开始

零值

变量已经被声明,但是未被显式初始化,这是变量将会被设置为零值。其它语言中,只声明未初始化的变量误用非常危险,但是,Go语言却坚持“零值可用”理念。在Go语言中合理利用零值确实带来不小的便利

  • int为0
  • float为0.0
  • bool为false
  • string为空串""(注意是双引号)
  • 指针类型为nil
  • 其它类型数据零值,学到再说

标识符本质

*每一个标识符对应一个具有数据结构的值,但是这个值不方便直接访问,程序员就可以通过其对应的标识符来访问数据,标识符就是一个指代。一句话,标识符是给程序员编程使用的。*标识符就是给人来看的,经过机器编译后,就是以内存地址的形式存在。

标识符写源代码时候,用来指代某个值的。编译后还有变量、常量标识符吗? 没有了,因为数据在内存中,内存访问靠什么?地址,标识符编译后就没有了就换成了地址了。

源代码本质是文本文件
编译 ,源代码编程成二进制可执行文件。运行这个磁盘上的二进制可执行文件,运行在当前OS上,变成进程,变量、常量、值在这块内存中放着

变量可见性

包级标识符

在Go语言中,在.go文件中的顶层代码中,定义的标识符称为包级标识符。如果首字母大写,可在包外可见。如果首字母小写,则包内可见。

在a.go的文件中
package main

// 无类型常量定义
var a = 20   // int
var b = 3.14 // float64
在m.go的文件中
package main

import "fmt"

func main() {
	fmt.Println(a, b)
}

使用建议

  • 顶层代码中定义包级标识符首字母大写作为包导出标识符,首字母小写作为包内可见标识符
  • const定义包级常量,必须在声明时初始化
  • var定义包级变量
    可以指定类型,也可以使用无类型常量定义
    延迟赋值必须指定类型,不然没法确定零值
  • 有相关关系的,可以批量定义在一起
  • 一般声明时,还是考虑“就近原则”,尽量靠近第一次使用的地方声明
  • 不能使用短格式定义
局部标识符

定义在函数中,包括main函数,这些标识符就是局部标识符。

使用建议

  • 在函数中定义的标识符

  • const定义局部常量

  • var定义局部变量

    可以指定类型,也可以使用无类型常量定义
    延迟赋值必须指定类型,不然没法确定零值

  • 有相关关系的,可以批量定义在一起

  • 在函数内,直接赋值的变量多采用短格式定义

布尔型

类型bool,定义了2个预定义常量,分别是true、false。

bool在go中不是int类型,也不是其他整数类型。在go中,bool就是布尔型,和整型没有关系,就是完全不同的类型。

数值型

整型

  • 长度不同:int8、int16(C语言short)、int32、int64(C语言long)

  • 长度不同无符号:uint8、unit16、uint32、uint64

    • byte类型,它是uint8的别名
  • 自动匹配平台:int、uint

    • int类型它至少占用32位,但一定注意它不等同于int32,不是int32的别名。要看CPU,32位就是4字节,64位就是8字节。但是,也不是说int是8字节64位,就等同于int64,它们依然是不同类型!

    以上类型均不相同,但是独立的类型

    package main
    
    import "fmt"
    
    func main() {
    	var a = 20
    	b := 30
    	var c int = 40
    	fmt.Printf("%T, %T, %T, %d\n", a, b, c, a+b+c)
    }
    int, int, int, 90
    
    
    看区别
    
    package main
    
    import "fmt"
    
    func main() {
    	var a = 20
    	b := 30
    	var c int = 40
    	fmt.Printf("%T, %T, %T, %d\n", a, b, c, a+b+c)
    	var d int64 = 50
    	fmt.Printf("%T, %T\n", d, a+d)  // a是int类型  d是int64  不是一个类型 必须同类型才能相加
    }
    
    
    package main
    
    import "fmt"
    
    func main() {
    	var a = 20
    	b := 30
    	var c int = 40
    	fmt.Printf("%T, %T, %T, %d\n", a, b, c, a+b+c)
    	var d int64 = 50
    	fmt.Printf("%T, %T\n", d, a+int(d))
    }
    int64, int   //d是int64  将强制类型转换为int类型
    
    

    %d 数值形式,往往用于整数

    %T 表示type,取值的类型

强制类型转换

把一个值从一个类型强制转换到另一种类型,有可能转换失败。

package main
import "fmt"
func main() {
var d int64 = 50
fmt.Printf("%T, %d\n", d, d)
fmt.Printf("%T, %s; %T, %d; %T, %f\n", string(d), string(d), rune(d),
rune(d), float32(d), float32(d))
}
输出如下
int64, 50
string, 2; int32, 50; float32, 50.000000

%T 表示type,取值的类型
%d digital 数值形式,往往用于整数
%s 用string类型的值
%q 带字符串类型引号的%s,quote引号
%c character,字符输出
%f float浮点数输出,默认精度为6

字符和整数

字符表达,必须使用单引号引住一个字符。

单引号留给了表示字符,字面量表达,本质上是int32(rune)或byte(uint8)

双引号和反引号用来表示字符串字面量。

type rune = int32 // rune是int32的别名,4个字节,可以是Unicode字符
type byte = uint8 // byte是uint8的别名,1个字节
package main

import "fmt"

func main() {
	var c rune = '中'                     // 字符用单引号
	fmt.Printf("%T, %[1]c, %[1]d\n", c)   // int32, 中, 20013
}
[1] 代表的是指定后面的序号

    c = 'a'
    fmt.Printf("%T, %c, %d\n", c, c, c) // int32, a, 97

	var d byte = '中' // 错误,超出byte范围  byte是1个字节 但是中是四个字节的  转换出来超出byte的范围
	
	

浮点数

float32:最大范围约为3.4e38,通过math.MaxFloat32查看
float64:最大范围约为1.8e308,通过math.MaxFloat64查看
打印格式化符常用%f

// fmt的格式化,参考包帮助 https://pkg.go.dev/fmt
f := 12.15
fmt.Printf("%T, %f\n", f, f) // 默认精度6
fmt.Printf("%.3f\n", f)    // 小数点后3位
fmt.Printf("[%3.2f]\n", f)  // 宽度撑爆了,中括号加上没有特殊含义,只是为了看清楚占的
打印宽度
fmt.Printf("[%6.2f]\n", f)  // 宽度为6,保留两位小数
fmt.Printf("[%-6.2f]\n", f)  // 左对齐

你可能感兴趣的:(go,golang,开发语言,后端)