1.并发概念概述
并发指的是同一时间的多次访问。解决并发途径一般就是创建多个服务器去分流访问,
对于服务器而言,响应速度越快那么并发量肯定就越高。
或者是通过语言逻辑来解决分流。go语言对于并发天生支持性就非常好
ps:打开mac系统终端快捷方式 cmd+space
ps:查看go安装版本 go version
2.字符和字符串的区别
1)转义字符
go语言中使用\反斜线表示转义字符,\反斜线配合其他的字符进行组合能够在字符串中拥有特殊的含义
例如:
\n 换行
\r 回车
\\ 输出单一反斜线
\" 双引号
\0 字符串结束符号
ps:在很多语言中\'转义字符都用来表示单引号,但是在go语言中却并不存在这样的转义字符。
其原因是因为在go语言中''单引号是用来表示字符的,并不能用于创建字符串。
字符串仅能够通过""双引号来定义,因此在双引号之内使用单引号的做法不会报错。
ps:\0转义字符是一个非常特殊的转义字符,本转义字符表示的是一个“边界”的含义。
本字符一般不能够在字符串内部显式写出表示,而是仅仅在程序执行的时候在内存中进行生效。
如果在字符串中显示写出,也表示的是八进制数而不是\0结束位(077 014这样的值)
例如%s等占位符进行格式化输入输出的时候就会通过检测\0来实现。
2)字符串操作方法,获取长度len()
var str1 string = 'hello';
var str2 string = '你好';
num1:=len(str1);//5;
num2:=len(str2);//6
ps:go语言中每一个中文字符占有3个字符位数,这是为了与linux系统进行对应统一。
3.占位符的使用
1)特殊占位符
%T 打印变量对应的数据类型
var num1 float64 = 10;
fmt.Printf("%T", num1);//float64
%% 直接打印%百分号本身
fmt.Printf("35%%");//35%
2)进制与进制转换
八进制:go语言中八进制的数据采用0开头,后面的内容中不允许有超过7的数字
num:=0123; //相当于十进制中64*1+8*2+1*3
十进制:go语言中的数据主要采用十进制。
num:=123;
十六进制:go语言中十六进制的数据采用0x开头,后面的内容由abcdef加数字组成
num:=0x123 //相当于十进制中256*1+16*2+1*3
ps:在go语言中不能够直接表示二进制数据,但是可以通过%b进行二进制格式化输出。
fmt.Printf("%b",num);
ps:在go语言中可以通过%o进行八进制格式化输出
fmt.Printf("%o",num);
ps:在go语言中可以通过%x或%X来进行十六进制的格式化输出,其区别在于输出显示是小写还是大写
fmt.Printf("%x",num);//0x12ab
fmt.Printf("%X",num);//0x12AB
ps:%q用于切片,暂且搁置,后续补充...
4.常量
在go语言中使用关键字const来定义常量,常量的命名规范等同于变量。
但区别在于常量在定义完成后,其值不能发生改变。
eg:
const num int = 10;
num = 100;
fmt.Println(num);//cannot assign to num(即常量不能修改!)
ps:常量和变量虽然都是存放于内存之中,但是存储的位置却截然不同。
常量存储于数据区,但是变量可能缺存储于栈区。
ps:常量不允许直接输出内存地址,只能访问其值,即参与计算
ps:栈区是系统为每一个应用程序分配的1M的空间来存储变量,在程序运行结束以后系统会将其自动释放。
ps:数据区可以再细分为【初始化数据区】【未初始化数据区】【常量区】
ps:常量一般在程序中采用大写来表示。用于和变量做出区分
ps:字面常量指的是像123 "abc"等这样直接表示的数据,字面常量也存放于数据区的常量区之内
字面常量其实算是一种硬常量,即不需要计算机进行解析,就能够直接进行使用的常量。
5.iota枚举
iota是go语言中常量声明的一个枚举器,其用于生成一组以相似规则初始化的常量,
但是并不用每行都写一遍初始化的表达式。iota以整数值为常量赋值
eg:
const(
num1 = 10;
num2 = iota;
num3 = 100
num4 = iota;
num5 = 36;
num6
)
fmt.Println(num1,num2,num3,num4,num5,num6);//10,1,100,3,36,5
ps:在const声明语句中,iota会默认将第一行声明处设置为0值。
然后随着每一条声明语句逐次加一。这个规则与声明语句中是否使用了iota并无任何关系
ps:iota可以不在const常量声明结构的第一条语句中使用,也可以不连续使用
但iota枚举取值却仍然是从第一条语句设置为0值进行逐次递增。
ps:iota在定义枚举的时候,若多个常量写在同一条语句内,则这些常量取相同的常量值
const(
num1,num2 = iota;
num3 = iota;
)
fmt.Println(num1,num2,num3);//0,0,1
6.算术运算符
go语言中的算术运算符也仍然和c语言的规则大同小异。
算术运算符只要包括:
+ - * / % ++ --
分别表示加法、减法、乘法、除法、取余、自增、自减
ps:int整数类型与int整数类型的计算,结果为仍旧为整数。(10 / 4 = 2)
ps:%取余操作必须是对整数进行操作,对浮点数进行取余操作是宣告无效的。(10 % 2.5 => 无效计算)
(1)自增自减运算 ++ --
非常关键性的一点就是go语言中的自增自减运算与传统c语言中的自增自减运算完全不同。
在go语言中++和--只存在后运算,而不存在前运算规则。
(屏蔽了二一性问题,即同样运算表达式,不同设备的不同运算顺序导致的结果不同问题。
例如b+++a,有的设备计算过程是【b+】【++a】,有的设备计算过程是【b++】【+a】)
eg:
var num int = 10;
num++;//合法
num--;//合法
++num;//违法
--num;//违法
而另外一个非常匪夷所思的地方就是自增自减仅能够对变量自身生效,而无法进行“再次赋值”!
eg:
var num int = 10;
num1 := num++;//违法!
7.类型转换
(1)整数与浮点数的类型转换
在go语言中,不同数据类型的变量是不能够参与计算的。例如:
eg:
num1:=10;
num2:=3.14;
num3:=num1*num2;//违法
为了能够不同数据类型的变量都能够参与计算,提出了数据类型转换的语法:【类型转换格式(变量)】
这样就能够将变量转换为想要转变为的数据格式:
eg:
num1:=10;
num2:=3.14;
num3:=float64(num1)*num2;//31.400000000000002(浮点数的精度丢失问题)
ps:类型转换的过程中,将浮点类型数据转换成整形类型数据的时候,是舍掉小数位,而不是四舍五入掉小数位。
num1 := 10;
num2 := 3.99;
num3:=num1*int(num2);//30
(2)相同数据类型的类型转换
在go语言中,相同数据类型的变量有时也不能够互相参与计算。例如
eg:
var num1 float32 = 10;
var num2 float64 = 20;
num3 =: num1 * num2;//违法
必须也要通过类型转换成为完全相同的数据类型,才能够进行计算。同理其它数据类型也是一样的道理。
(3)转换规则
1)数据转换的时候通常会从精度低的向精度高的数据类型进行转换。
eg:float32=>float64。因为这样会避免因为存储空间有限导致的精度丢失问题。
2)若数据转换完成后的数据类型仍不是相同的数据类型,那么也不能够继续参与计算
eg:
var num1 float32 = 10;
var num2 int = 4;
num3 =: float64(num1) * num2;//仍旧是违法的
3)很多其他语言中的int=>string等这样的操作在go语言中是不允许的
eg:
var str string = "100";
var num int = 10;
result := int(str) + num;//违法操作!
8.赋值运算符
go语言中的赋值运算符,与传统c语言中的赋值运算基本没什么区别。
= += -= *= /= %=
9.关系运算符(比较运算符)
go语言中的关系运算符,与传统c语言中的关系运算符基本没什么区别。
== != > >= < <=
10.逻辑运算符
go语言中的逻辑运算符,与传统c语言中的逻辑运算符基本没什么区别。
&& || !
ps:go语言中的逻辑运算符只能对布尔类型变量,或布尔类型结果的表达式操作
var num1 int = 10;
var num2 int = 20;
num3 := (num1 && num2);//违法操作!
ps:go语言中的逻辑运算符由于只能操作布尔类型相关内容,
并且不能使用true,false以外的值表示布尔值
因此在go语言中短路运算是一种根本不存在的操作!!
11.指针运算符
go语言中的指针运算符,与传统c语言中的逻辑运算符基本没什么区别。
& *
eg:
var str string = "abc";
strPointer = &str;
newStr = *strPointer;
fmt.Println(strPointer); //0xc0007e030 &为取地址符
fmt.Println(newStr); //"abc" *为取地址的值符(指针)
fmt.Println(newStr[0]); //97 指针可直接读取值,但go中读的是ASCII编码
fmt.Println(newStr[0+2]); //99 指针可跳步计算,但go中计算结果仍是ASCII编码
fmt.Println(&newStr); //0xc00007e040 通过指针赋值,与通过变量赋值一样,但变量之间地址不同
12.运算符优先级
go语言中的运算符优先级,与传统c语言中的运算符优先级基本没什么区别
因此口诀可以直接拿来照搬即可:
初等单目一二级:
初等运算符【()小括号,.点运算,[]中括号】优先级最高,单目运算符【! & * ++ --】优先级次之
乘除加减求位移:
算术运算符 * /高于加减,然后是位移运算符<<左位移运算 >>右位移运算 >>>无符号右位移运算
关系等于不等于:
关系运算符 > >= < <= 高于 == !=
按位与来异或或:
位运算符 & ^ |
逻辑与或条件弱:
逻辑运算符中 && 高于 ||
赋值逗号一点破:
赋值运算符次低,逗号最低
//判断年份小案例
var year int = 0;
fmt.Println("请输入需要判断是否为闰年的年份:");
fmt.Scanf("%d",&year);
//输入后一次判断
var flag1 bool = (year>=0&&year<=9999);
var flag2 bool = ((year%4==0)&&(year%100!=0));
var flag3 bool = (year%400==0);
//判断后最终判断
var flag4 = flag1 && (flag2 || flag3);
//制造输出
if(flag4){
fmt.Printf("%d是闰年",year);
}else{
fmt.Printf("%d不是闰年",year);
}
13.流程控制分支语句
(1)if条件语句
if 表达式 {
内容
}
表示当表达式的结果为真的时候,执行大括号内的语句。
而如果表达式的结果为假,那么则直接跳过大括号的内容继续向后执行。
eg:
if num>10 {
fmt.Println(num);
}
注意:if后的表达式必须为布尔值,或计算结果为布尔值的表达式
任何int,float,string等类型的数据或表达式结果均必须不能作为判断依据!
即if num {...}这种写法完全错误!
了解:if后的表达式不能写小括号,这和c语言有着本质的区别
虽然写小括号也不算错,但是出于尊重go语言的语法规则来讲,最好不要写。
即 if num>0 {...} 最好不要写成 if (num>0){...}
重点:对于if语句而言,else语句是一个不可或缺的二元判断组成部分。
但是在go语言中,对于else的摆放位置做了强制规定
必须紧跟在if后{}大括号的后半部分,而不能重新另起一行!!
eg:
//正确语法
if num>0 {
...
}else{
...
}
//完全错误
if num>0 {
...
}
else{
...
}
(2)switch分支语句
switch 表达式{
case 结果1:
语句1;
case 结果2:
语句2;
...
default:
默认语句;
}
表示根据switch后表达式的结果,来选择大括号中的某一种case与之对应的语句情况执行。
而如果所有case后的结果都不能与switch后的表达式结果相匹配,则直接执行default后的默认语句。
eg:
switch num{
case 0:
fmt.Println('here is 0');
case 1:
fmt.Println('here is 1');
...
default:
fmt.Println('here is others');
}
注意:switch后的表达式可以是任意类型的结果,不必必须是一个布尔值
但是case后的计算结果必须和表达式的类型一致,否则会提示错误。
eg:
switch num*2{
case 100:
//正确!
case "str"
//错误!
}
了解:同样出于对go语法的尊重,case后的语句不采用大括号包裹。
直接书写即可。
重点:在go语言中switch的判断表达式最好不使用float浮点数来进行判断
因为浮点数在计算机中是一个大概的约数。
虽然go语言能够帮我们将浮点数的大小去处理妥当,但为了避免出现不可预知的问题
我们尽量不使用浮点数进行判断。
重点:在go语言中switch的每一个case之间不必使用break语句去间隔,
多个case语句自然而然的就只有一个会被执行。
重点:如果需要有多个case对应着同样的一段代码执行,那么需要多个case顺次进行执行
那么需要fallthrough关键字来进行说明。
eg:
switch num{
case 1:
case 2:
语句2;
default:
默认语句;
}
//次数num为1的时候,只会返回一个空白,而不会顺次执行case2的语句2!
//这和传统c语言有着明显的差别(其实也是好事,解决了掉落值的问题)
switch num{
case 1:
fallthrough;
case 2:
语句2;
default:
默认语句;
}
//而下面的这种添加了fallthrough的写法,则能够在满足条件1的情况下
//继续顺次执行case2中的语句2(完美将掉落差问题变成了可控操作。)
---------------------
作者:Frank·Ming
来源:CSDN
原文:https://blog.csdn.net/u013792921/article/details/84341709
版权声明:本文为博主原创文章,转载请附上博文链接!
有疑问加站长微信联系(非本文作者))