零基础!!1小时学会跨时代的一门新语言 《建议收藏》

Posted @了凡

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了零基础!!1小时学会跨时代的一门新语言 《建议收藏》相关的知识,希望对你有一定的参考价值。

前言

在这里插入图片描述

博主介绍:

– 本人是了凡,意思为希望本人任何时候以善良为先,以人品为重,喜欢了凡四训中的立命之学、改过之法、积善之方、谦德之效四训,更喜欢每日在简书上投稿每日的读书感悟笔名:三月_刘超。专注于 Go Web 后端,辅学Python、Java、算法、前端等领域。


文章目录


引言


官方解释语言来历

很久以前,有一个IT公司,这公司有个传统,允许员工拥有20%自由时间来开发实验性项目。在2007的某一天,公司的几个大牛,正在用c++开发一些比较繁琐但是核心的工作,主要包括庞大的分布式集群,大牛觉得很闹心,后来c++委员会来他们公司演讲,说c++将要添加大概35种新特性。这几个大牛的其中一个人,名为:Rob Pike,听后心中一万个xxx飘过,“c++特性还不够多吗?简化c++应该更有成就感吧”。于是乎,Rob Pike和其他几个大牛讨论了一下,怎么解决这个问题,过了一会,Rob Pike说要不我们自己搞个语言吧,名字叫“go”,非常简短,容易拼写。其他几位大牛就说好啊,然后他们找了块白板,在上面写下希望能有哪些功能(详见文尾)。接下来的时间里,大牛们开心的讨论设计这门语言的特性,经过漫长的岁月,他们决定,以c语言为原型,以及借鉴其他语言的一些特性,来解放程序员,解放自己,然后在2009年,go语言诞生。


主要特征

1.自动立即回收
2.更丰富的内置类型
3.函数多返回值
4.错误处理
5.匿名函数和闭包
6.类型和接口
7.并发编程
8.反射
9.语言交互性
10.既面向过程也面向对象


优点

自带gc。
静态编译编译好后扔服务器直接运行。
简单的思想,没有继承,多态,类等
丰富的库和详细的开发文档。
语法层支持并发,和拥有同步并发的channel类型,使并发开发变得非常方便。
简洁的语法,提高开发效率,同时提高代码的阅读性和可维护性。
超级简单的交叉编译,仅需更改环境变量。
Go 语言是谷歌 2009 年首次推出并在 2012 年正式发布的一种全新的编程语言,可以在不损失应用程序性能的情况下降低代码的复杂性。谷歌首席软件工程师罗布派克(Rob Pike)说:我们之所以开发 Go,是因为过去10多年间软件开发的难度令人沮丧。Google 对 Go 寄予厚望,其设计是让软件充分发挥多核心处理器同步多工的优点,并可解决面向对象程序设计的麻烦。它具有现代的程序语言特色,如垃圾回收,帮助开发者处理琐碎但重要的内存管理问题。Go 的速度也非常快,几乎和 C 或 C++ 程序一样快,且能够快速开发应用程序


最大优点

Go语言为并发而生:
Go语言的并发是基于 goroutine 的,goroutine 类似于线程,但并非线程。可以将 goroutine 理解为一种虚拟线程。Go 语言运行时会参与调度 goroutine,并将 goroutine 合理地分配到每个 CPU 中,最大限度地使用CPU性能。开启一个goroutine的消耗非常小(大约2KB的内存),你可以轻松创建数百万个goroutine

goroutine的特点:
具有可增长的分段堆栈。意味着它们只在需要时才会使用更多内存。
goroutine的启动时间比线程快
goroutine原生支持利用channel安全地进行通信
goroutine共享数据结构时无需使用互斥锁


准备学习前讲解


语言IDE编辑器安装包及开发环境(全套)

链接:https://pan.baidu.com/s/18di4xhP-rvCt0xHeJkV15A
提取码:AAAA


安装教程讲解

参考:https://www.jb51.net/article/200627.htm


语言结构

基础组成有以下几个部分:
包声明

package main  // 以 package 关键字作为包声明 后面加上当前包名

引入包

import "fmt"  // 以 import 关键字作为引入包 后面加上要引入的包名 这里暂时举例fmt 数据格式化包为举例,后序讲解具体用法

函数

func main() {}  // 以 func 关键字作为声明函数或者方法  后面跟你要声明的函数名或者方法名

变量

var a string = "hello"  // 这里先声明一个字符串格式的 hello 后面细节讲解

语句 & 表达式

if 布尔表达式 {
   /* 在布尔表达式为 true 时执行 */
}    // 这里暂时举例一种表达式为 if 语句  后面分别讲解 if、for、goto、switch...

注释

 /*...*/    // 多行注释
 //         // 单行注释

语言基础语法

语法简讲

fmt.Println("Hello, World!")

上述代码分别是由关键字,标识符,常量,字符串,符号组成

1. fmt  // 关键字
2. .    // 标识符
3. Println  // 关键字
4. (  // 符号
5. "Hello, World!"  // 字符串
6. )  // 符号

分割

go的多行数书写不需要用 ; 分号做间隔像C语言一样书写 和 Python 写法有一点相似

注释

注释不会被编译

单行注释用// 进行注释

// 单行注释

多行注释用/* */进行注释

/*
 多行注释
 */

标识符

标识符用来命名变量、类型等程序实体

不能以数字开头、不能是Go 语言的关键字、不能用运算符

举例:
1ab 以数字开头
func 是Go 语言的关键字
a+b 用运算符

关键字

25 个关键字或保留字:
在这里插入图片描述
还有 36 个预定义标识符:
在这里插入图片描述


语法之变量

变量初始化

单个初始化

var 变量名 类型 = 表达式

多个初始化

var 变量名1, 变量名2  = 表示式1, 表达式2

变量声明

单个声明

var 变量名 变量类型
// 例如:
var a string = "hello" // 声明一个名叫做 a 字符串类型的变量

多个声明

var (
    one string  // 声明一个名叫做 one 字符串类型的变量
    two int     // 声明一个名叫做 two 整型类型的变量
    three bool  // 声明一个名叫做 three 布尔类型的变量
)

全局声明

在程序的任意一行代码都可以引用的变量

局部声明

函数内部,可以使用更简略的 := 方式声明并初始化变量

举例:

package main

import (
	"fmt"
)
// 全局变量
var All = 10

func main() {
	n := 30
	toPo := 20 // 局部变量
	fmt.Println(toPo, n)
}

打印结果:
在这里插入图片描述

常量声明

单个常量声明

count a string = "hello" // 声明一个名叫做 a 字符串类型的常量

多个常量声明

count (
    one string  // 声明一个名叫做 one 字符串类型的常量
    two int     // 声明一个名叫做 two 整型类型的常量
    three bool  // 声明一个名叫做 three 布尔类型的常量
)

匿名变量

如果想要忽略某一个返回值的时候可以使用以_下划线符号来做匿名变量返回值
例如:

package main

import "fmt"

func fun1()(int, int)  {
	return 1, 2
}
func main() {
	_, b := fun1()  // 这里使用匿名返回值,对1返回值进行忽略掉
	fmt.Println(b)
}

打印结果:
在这里插入图片描述
iota

iota 是一个常量计数器
目前没有发现什么大的用处

在这里插入图片描述

具体可以看:https://segmentfault.com/a/1190000023532777


语法之数据类型

整型

普通整型

普通整型:uint8 无符号 8位整型 (0 到 255) int8 有符号 8位整型 (-128 到 127)

特殊整型

特殊整型:uint 32位操作系统上就是uint32,64位操作系统上就是uint64 int 32位操作系统上就是int32,64位操作系统上就是int64 uintptr 无符号整型,用于存放一个指针
注意: 在使用int和 uint类型时,不能假定它是32位或64位的整型,而是考虑int和uint可能在不同平台上的差异。

进制表示

二进制: v := 0b00101101, 代表二进制的 101101,相当于十进制的 45
八进制:v := 0o377,代表八进制的 377,相当于十进制的 255
十进制: 不做改变
十六进制:v := 0x1p-2,代表十六进制的 1 除以 2²,也就是 0.25
而用 _ 来分隔数字,比如说: v := 123_456 表示 v 的值等于 123456

浮点型

float32

float32 的浮点数的最大范围约为 3.4e38,可以使用常量定义:math.MaxFloat32

float64

float64 的浮点数的最大范围约为 1.8e308,可以使用一个常量定义:math.MaxFloat64

复数

复数有实部和虚部,complex64的实部和虚部为32位,complex128的实部和虚部为64位。

布尔值

两种状态:

以bool类型进行声明布尔型数据,布尔型数据只有true(真)和false(假)两个值

注意

1.布尔类型变量默认值为false。
2.不允许将整型强制转换为布尔型。
3.布尔型无法参与数值运算,也无法与其他类型进行转换。

字符串

单行声明

s1 := "hello"

多行声明
使用反引号字符 列如:

s1 := `第一行
	   第二行
	   第三行
	  ` 

注意:反引号间换行将被作为字符串中的换行,但是所有的转义字符均无效,文本将会原样输出

字符串必会:

字符串的内部实现使用UTF-8编码
— — — — — —
求长度:
len(str)
— — — — — —
拼接字符串
+或fmt.Sprintf
— — — — — —
分割
strings.Split
— — — — — —
判断是否包含
strings.contains
— — — — — —
前缀/后缀判断
strings.HasPrefix,strings.HasSuffix
— — — — — —
子串出现的位置
strings.Index(),strings.LastIndex()
— — — — — —
join操作
strings.Join(a[]string, sep string)

byte和rune类型

byte 类型

uint8类型,或者叫 byte 型,代表了ASCII码的一个字符
Go 使用了特殊的 rune 类型来处理 Unicode,让基于 Unicode 的文本处理更为方便,也可以使用 byte 型进行默认字符串处理,性能和扩展性都有照顾

rune 类型

rune类型,代表一个 UTF-8字符
需要处理中文、日文或者其他复合字符时,则需要用到rune类型。rune类型实际是一个int32

字符串底层是一个byte数组,所以可以和[]byte类型相互转换。字符串是不能修改的 字符串是由byte字节组成,所以字符串的长度是byte字节的长度。 rune类型用来表示utf8字符,一个rune字符由一个或多个byte组成

结论:rune比byte大

类型转换

Go语言中只有强制类型转换,没有隐式类型转换。该语法只能在两个类型之间支持相互转换的时候使用

格式:T(表达式)   

T表示要转换的类型。表达式包括变量、函数返回值等

实战

编写代码统计出字符串"hello沙河小王子"中汉字的数量。

答案:

package main

import "fmt"

func main()  {
	a := 0
	s1 := "hello沙河小王子"
	for _, i := range s1 {
		if i > 'z' {
			a ++
		}
	}
	fmt.Println(a)
}


运行结果:
在这里插入图片描述


语法之运算符

算数运算符

+ 相加
- 相减
* 相乘
/ 相除
% 求余
++(自增)和 --(自减)在Go语言中是单独的语句,并不是运算符,Go语言中只可以后--不可以前--++也一样

关系运算符

== 检查两个值是否相等,如果相等返回 True 否则返回 False。
!= 检查两个值是否不相等,如果不相等返回 True 否则返回 False。
> 检查左边值是否大于右边值,如果是返回 True 否则返回 False。
>= 检查左边值是否大于等于右边值,如果是返回 True 否则返回 False。
< 检查左边值是否小于右边值,如果是返回 True 否则返回 False。
<= 检查左边值是否小于等于右边值,如果是返回 True 否则返回 False。

逻辑运算符

&& 逻辑 AND 运算符,如果两边的操作数都是 True,则为 True,否则为False。
|| 逻辑 OR 运算符, 如果两边的操作数有一个 True,则为 True,否则为 False。
!逻辑 NOT 运算符, 如果条件为 True,则为 False,否则为 True。

位运算符

& 参与运算的两数各对应的二进位相与。(两位均为1才为1)
| 参与运算的两数各对应的二进位相或。(两位有一个为1就为1)
^参与运算的两数各对应的二进位相异或,当两对应的二进位相异时,结果为1。(两位不一样则为1)
<< 左移n位就是乘以2的n次方。“a<<b”是把a的各二进位全部左移b位,高位丢弃,低位补0。
>> 右移n位就是除以2的n次方。“a>>b”是把a的各二进位全部右移b位。

赋值运算符

= 简单的赋值运算符,将一个表达式的值赋给一个左值
+= 相加后再赋值
-= 相减后再赋值
*= 相乘后再赋值
/= 相除后再赋值
%= 求余后再赋值
<<= 左移后赋值
>>= 右移后赋值
&= 按位与后赋值
|= 按位或后赋值
^= 按位异或后赋值

实战

有一堆数字,如果除了一个数字以外,其他数字都出现了两次,那么如何找到出现一次的数字?

答案:

package main

import "fmt"

func main()  {
	var nums  = []int {5,7,8,8,9,7,9}
	i := 0
	for j := 0; j < len(nums); j ++ {
		i = i ^ nums[j]
	}
	fmt.Println(i)
}

执行结果
在这里插入图片描述


语法之流程控制

if else(分支结构)

基础写法:

if 表达式1 {
    分支1
} else if 表达式2 {
    分支2
} else{
    分支3
}

规定与if/else匹配的左括号{必须与if/else和表达式放在同一行,{放在其他位置会触发编译错误

特殊写法

if条件判断还有一种特殊的写法,可以在 if 表达式之前添加一个执行语句,再根据变量值进行判断

for(循环结构)

Go 语言中的所有循环类型均可以使用for关键字来完成

基础写法

for 初始语句;条件表达式;结束语句{
    循环体语句
}

初始语句,条件表达式,结束语句三者都可以省略,也可以理解为单独的三个部分

无限循环

for循环可以通过break、goto、return、panic语句强制退出循环,也可以配合goto,return,panic完成其他事情,不一定非要死循环中使用

for range(热键循环)

for range遍历数组、切片、字符串、map 及通道(channel)。
数组、切片、字符串返回索引和值。
map返回键和值。
通道(channel)只返回通道内的值。

switch case(分支结构)

使用switch语句可方便地对大量的值进行条件判断
Go语言规定每个switch只能有一个default分支

一个分支可以有多个值,多个case值中间使用英文逗号分隔

switch n := 7; n {
	case 1, 3, 5, 7, 9:
		fmt.Println("奇数")

分支还可以使用表达式,这时候switch语句后面不需要再跟判断变量

age := 30
	switch {
	case age < 25:
		fmt.Println("你的年龄是",age,"岁")

fallthrough语法可以执行满足条件的case的下一个case,是为了兼容C语言中的case设计的

举例:

package main

import "fmt"

func main() {
	s := "a"
	switch {
	case s == "a":
		fmt.Println("a")
		fallthrough
	case s == "b":
		fmt.Println("b")
	}
}

运行结果
在这里插入图片描述

goto(跳转到指定标签)

goto语句通过标签进行代码间的无条件跳转。goto语句可以在快速跳出循环、避免重复退出上有一定的帮助。Go语言中使用goto语句能简化一些代码的实现过程

举例:

package main

import "fmt"

func main() {
	Demo()
}
func Demo() {
	for i := 0; i < 10; i++ {
		for j := 0; j < 10; j++ {
			if j == 2 {
				// 设置退出标签
				goto breakTag
			}
			fmt.Printf("%v-%v\\n", i, j)
		}
	}
	return
	// 标签
breakTag:
	fmt.Println("结束for循环")
}

运行结果
在这里插入图片描述

break(结束循环)

break语句可以结束for、switch和select的代码块

break语句还可以在语句后面添加标签,表示退出某个标签对应的代码块,标签要求必须定义在对应的for、switch和 select的代码块上

例如:

package main

import "fmt"

func main() {
	Demo()
}
func Demo() {
DEMO:
	for i := 0; i < 10; i++ {
		for j := 0; j < 10; j++ {
			if j == 2 {
				break DEMO
			}
			fmt.Printf("%v-%v\\n", i, j)
		}
	}
	fmt.Println("...")
}

在这里插入图片描述

continue(继续下一个循环)

continue语句可以结束当前循环,开始下一次的循环迭代过程,仅限在for循环内使用。

在 continue语句后添加标签时,表示开始标签对应的循环

举例

package main

import "fmt"

func main() {
	Demo()
}
func Demo() {
loop:
	for i := 0; i < 5; i++ {
		for j := 0; j < 5; j++ {
			if i == 2 && j == 2 {
				continue loop
			}
			fmt.Printf("%v-%v\\n", i, j)
		}
	}
}

运行结果
在这里插入图片描述

实战

编写代码打印9*9乘法表

答案:

package main

import "fmt"

func main() {
	for i := 1; i <= 9; i++ {
		for j := 1; j <= i; j++ {
			fmt.Printf("%d * %d = %-2d  ", i, j, i*j)
		}
		fmt.Println()
	}
}

执行结果
在这里插入图片描述


语法之数组

基础语法

// 定义一个长度为6元素类型为int的数组a
var a [6]int

数据定义

var 数组变量名 [元素数量]T

数组的长度必须是常量,并且长度是数组类型的一部分。 [5]int和[10]int是不同的类型。

两种相等类型的数组可以直接交换值

 var num = []int {2,3,5}
	var nums = []int {3,8,7}
	num, nums = nums, num
	fmt.Println(num, nums)

数组可以通过下标进行访问,下标是从0开始,最后一个元素下标是:len-1,访问越界(下标在合法范围之外),则触发访问越界,会panic

数组的初始化

方法一:

初始化数组时可以使用初始化列表来设置数组元素的值

//数组会初始化为int类型的零值
var testArray [3]int    

//使用指定的初始值完成初始化
var numArray = [3]int{1, 2}   

//使用指定的初始值完成初始化
var cityArray = [3]string{"北京", "上海", "深圳"} 

方法二:

也可以不写长度,编译器根据初始值的个数自行推断数组的长度

var testArray [3]int

var numArray = [...]int{1, 2}

var cityArray = [...]string{"北京", "上海", "深圳"}

方法三:

可以使用指定索引值的方式来初始化数组

a := [...]int{1: 1, 3: 5}
	fmt.Println(a)    // [0 1 0 5]

数组初始化后默认是0

数组的遍历

方法一:

// 方法1:for循环遍历
	for i := 0; i < len(a); i++ {
		fmt.Println(a[i])
	}

方法二:

以上是关于零基础!!1小时学会跨时代的一门新语言 《建议收藏》的主要内容,如果未能解决你的问题,请参考以下文章

零基础学python第三课, 程序的执行原理注释运算符

零基础学python第三课, 程序的执行原理注释运算符

如何学习一门新语言

零基础1小时入门Vue(建议收藏)

[Go] 开始试探一门新语言的五点思考 - Golang

零基础1小时入门Vue(建议收藏)