Go基础知识总结

变量声明

Go语言中的变量需要声明以后才可以使用(需要提前定义变量)并且声明后必须使用(不适用会报错)

标准声明

var 变量名 变量类型

example:

var name string
var id int
var isOk bool

多变量声明可以整合在一起

var (
name string
id int
isOk bool )

变量初始化

Go语言在声明变量的时候,会自动对变量对应的内存区进行初始化操作。

var 变量名 变量类型 = 表达式

example:

var name string = "A2rcher"
var id int = 123

类型推断

Go语言提供了一种简易的方式,不需要提供变量类型,可以根据后面的初始化操作后自动推断其变量类型

var name = "A2rcher"
var id = 123

短变量声明

在之后学习到的函数中,还可以用更简单的方式来声明一个变量(也是最常用的声明方法),使用:=声明并初始化变量

package main
import (
"fmt"
)
var m = 100 //全局变量 func main(){
n:=100
m:=300//声明并初始化局部变量
fmt.Println(m, n)
}

匿名变量

所谓匿名,通俗的讲就是没有名字的变量,用下划线_表示,匿名变量不占用命名空间(Go语言中变量声明后必须使用,匿名变量除外),不会分配内存,所以匿名变量之间不存在重复声明。

package main

import "fmt"

func foo() (string, int) {

	return "A2rcher", 20
} func main() {
x, _ := foo()
_, y := foo() fmt.Println("x=", x, "y=", y) }

常量

变量中还有一中是常量,它相对于变量来讲是永恒不变的值,对于变量来说一开始可以不做赋值直接定义类型,但是对于常量来讲他需要在定义的时候就要赋值,用const

const p = 3.1415
const e = 2.7182

多常量声明可以整合在一起

const (
p = 3.1415
e = 2.7182
)

iota常量计算器

iota是Go语言中的常量计算器,在常量表达式中使用。

package main

import "fmt"

const (
n1 = iota
n2
n3
n4
) func main() { fmt.Println(n1)//0
fmt.Println(n2)//1
fmt.Println(n3)//2
fmt.Println(n4)//3
}

iota在const关键字出现时将被重置为0。const中每新增一行常量声明将使iota计数一次(iota可理解为const语句块中的行索引)。 使用iota能简化定义,在定义枚举时很有用。

使用下划线_可以跳过其中一个

package main

import "fmt"

const (
n1 = iota//0
_ //1
n2 //2
n3 //3
n4 //4
) func main() { fmt.Println(n1)//0
fmt.Println(n2)//2
fmt.Println(n3)//3
fmt.Println(n4)//4
}

数据类型

整型

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

特殊整型

类型 描述
uint 32位操作系统上就是uint32,64位操作系统上就是uint64
int 32位操作系统上就是int32,64位操作系统上就是int64
uintptr 无符号整型,用于存放一个指针

浮点型

Go语言支持两种浮点型数:float32float64。这两种浮点型数据格式遵循IEEE 754标准: float32 的浮点数的最大范围约为 3.4e38,可以使用常量定义:math.MaxFloat32float64 的浮点数的最大范围约为 1.8e308,可以使用一个常量定义:math.MaxFloat64

打印浮点数时,可以使用fmt包配合动词%f,代码如下:

package main
import (
"fmt"
"math"
)
func main() {
fmt.Printf("%f\n", math.Pi)
fmt.Printf("%.2f\n", math.Pi)
}

复数

complex64和complex128

var c1 complex64
c1 = 1 + 2i
var c2 complex128
c2 = 2 + 3i
fmt.Println(c1)
fmt.Println(c2)

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

布尔

字符串

byte和rune

运算符

运算符 描述
+ 相加
- 相减
* 相乘
/ 相除
% 求余
运算符 描述
== 检查两个值是否相等,如果相等返回 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位。
运算符 描述
= 简单的赋值运算符,将一个表达式的值赋给一个左值
+= 相加后再赋值
-= 相减后再赋值
*= 相乘后再赋值
/= 相除后再赋值
%= 求余后再赋值
<<= 左移后赋值
>>= 右移后赋值
&= 按位与后赋值
|= 按位或后赋值
^= 按位异或后赋值

流程控制

if else

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

example:

package main

import "fmt"

func main() {
for i := 0; i < 10; i++ {
fmt.Println(i)
}
}

for循环的初始语句可以被忽略,但是用作与隔开的分号;还是要有的。

package main

import "fmt"

var i = 0

func main() {
for ; i < 10; i++ {
fmt.Println(i)
}
}

for循环的结束语句也是可以省略掉的

package main

import "fmt"

var i = 0

func main() {
for i < 10 {
fmt.Println(i)
i++
}
}

for range(键值循环)

键值循环可以用作与遍历,切片,map还有channel。遵循一下规律

  1. 数组、切片、字符串返回索引和值。
  2. map返回键和值。
  3. 通道(channel)只返回通道内的值。

switch

goto(跳转指定标签)

goto的使用可以这么理解,在一个循环中当运行到某一个位置时我不想让他继续运行下去而是跳到其他的地方,这个时候就可以使用goto,用来简化一些代码的实现过程。

func gotoDemo1() {
var breakFlag bool
for i := 0; i < 10; i++ {
for j := 0; j < 10; j++ {
if j == 2 {
// 设置退出标签
breakFlag = true
break
}
fmt.Printf("%v-%v\n", i, j)
}
// 外层for循环判断
if breakFlag {
break
}
}
}

使用goto语句能简化代码:

func gotoDemo2() {
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

跳出循环

continue

继续下次循环

数组

数组定义

var 变量名 [元素数量]T
var a [3]int
var b [4]string

数组初始化

package main

import "fmt"

func main() {

	var testArray [3]int
var numArray = [3]int{1, 2, 3}
var strArray = [3]string{"a", "b", "c"}
fmt.Println(testArray)
fmt.Println(numArray)
fmt.Println(strArray)
}

使用[...]可以根据初始值自动判断元素有多少

package main

import "fmt"

func main() {

	var testArray [3]int
var numArray = [...]int{1, 2, 3,4,5}
var strArray = [...]string{"a", "b", "c", "d","f","v"}
fmt.Println(testArray)
fmt.Println(numArray)
fmt.Println(strArray)
}

数组遍历

for循环遍历

package main

import "fmt"

func main() {

	var testArray [3]int
var numArray = [...]int{1, 2, 3, 4, 5}
var strArray = [...]string{"a", "b", "c", "d", "f", "v"}
fmt.Println(testArray)
fmt.Println(numArray)
fmt.Println(strArray)
for i := 0; i < len(numArray); i++ {
fmt.Println(i)
}
for v := 0; v < len(strArray); v++ {
fmt.Println(strArray[v]) }
}

for range遍历

package main

import "fmt"

func main() {

	var testArray [3]int
var numArray = [...]int{1, 2, 3, 4, 5}
var strArray = [...]string{"a", "b", "c", "d", "f", "v"}
fmt.Println(testArray)
fmt.Println(numArray)
fmt.Println(strArray)
for i, v := range numArray {
fmt.Println(i, v)
}
fmt.Println("----------------------------------------------------")
for m, n := range strArray {
fmt.Println(m, string(n))
}
}

运行结果可以明显看出他两个是有区别的。

for循环遍历的结果并没有把角标打印出来,而是直接出的结果。

for range循环遍历的结果时把对应的角标也打印了出来,所以我们可以改善一下,使用匿名变量可以让for range的结果for循环的结果一样。

package main

import "fmt"

func main() {

	var testArray [3]int
var numArray = [...]int{1, 2, 3, 4, 5}
var strArray = [...]string{"a", "b", "c", "d", "f", "v"}
fmt.Println(testArray)
fmt.Println(numArray)
fmt.Println(strArray)
for _, v := range numArray {
fmt.Println(v)
}
fmt.Println("----------------------------------------------------")
for _, n := range strArray {
fmt.Println(string(n))
}
}

同样的原理,可以对多为数组进行遍历。

切片

切片跟数组很像,但是切片相当于在数组类型的基础上做了一层封装,相较于数组可以更快的操作一块数据集合。

切片定义

var 变量名 [元素个数]T

可以看到他的定义方式跟数组一模一样,所以他的初始化也是一样的。

切片长度和容量

用内置函数len(),cap()可以求出切片的长度容量

package main

import "fmt"

func main() {

	var test1Slice [3]int
fmt.Println(len(test1Slice))
fmt.Println(cap(test1Slice))
var test2Slice = [...]string{"a", "b", "c", "d", "e", "f"}
fmt.Println(len(test2Slice))
fmt.Println(cap(test2Slice))
}

表达式

切片表达式中有low和high两个定义来表示切片中的界限值

func main() {
a := [5]int{1, 2, 3, 4, 5}
s := a[1:3] // s := a[low:high]
fmt.Printf("s:%v len(s):%v cap(s):%v\n", s, len(s), cap(s))
}
a[2:]  // 等同于 a[2:len(a)]
a[:3] // 等同于 a[0:3]
a[:] // 等同于 a[0:len(a)]

make()函数构造切片

make([]T,元素数量,切片容量)

example:

func main(){
a := make([]int,2,10)
}

参考

判断切片是否为空

一定要使用len(s)==0来判断,不能使用nil比较来判断。

append()方法添加元素

append()方法为切片同台添加元素,可以一次添加一个或者多个,还可以添加另一个其他切片中的元素。

package main

import "fmt"

func main() {
var s []int
s = append(s, 1)
s = append(s, 2, 3, 4)
s2 := []int{2, 3, 4}
s = append(s, s2...)
fmt.Println(s)
}

map使用

map:是一种无序的基于key-value的数据结构,必须初始化才可以使用。

map定义

map[keyType]valueType
  • KeyType:表示键的类型。
  • ValueType:表示键对应的值的类型。

map初始化

map默认初始值为nil,使用make()函数分配内存初始化:

make(map[keyType]valueType,[cap])

其中cap表示map的容量,该参数虽然不是必须的,但是我们应该在初始化map的时候就为其指定一个合适的容量。

map使用

package main

import "fmt"

func main() {

	sourceMap := make(map[string]int, 20)
sourceMap["A2rcher"] = 20
sourceMap["emo"] = 30
fmt.Println(sourceMap)
fmt.Printf("type %T\n", sourceMap) }

map可以在声明的时候就填充元素:

package main

import "fmt"

func main() {

	sourceMap := make(map[string]int, 20)
sourceMap["A2rcher"] = 20
sourceMap["emo"] = 30
fmt.Println(sourceMap)
fmt.Printf("type %T\n", sourceMap)
fmt.Println("***************")
sourceTest := map[string]int{
"lucher": 20,
"xs":10,
}
fmt.Println(sourceTest) }

判断键值对是否存在

package main

import "fmt"

func main() {

	sourceMap := make(map[string]int, 20)
sourceMap["A2rcher"] = 20
sourceMap["emo"] = 30
fmt.Println(sourceMap)
fmt.Printf("type %T\n", sourceMap)
fmt.Println("***************")
sourceTest := map[string]int{
"lucher": 20,
"xs": 10,
}
fmt.Println(sourceTest)
fmt.Printf("type %T\n", sourceTest) fmt.Println("______________________________")
v, ok := sourceMap["emo"]
if !ok {
fmt.Println("查无此人")
} else {
fmt.Println(v)
} }

map遍历

for range遍历

package main

import "fmt"

func main() {

	sourceMap := make(map[string]int, 20)
sourceMap["a"] = 90
sourceMap["b"] = 100
sourceMap["c"] = 60 for k, v := range sourceMap {
fmt.Println(k, v)
}
}

如果只想遍历前面的key时,可以把v省略。但要是想遍历value时,就需要匿名变量的帮助了。

package main

import "fmt"

func main() {

	sourceMap := make(map[string]int, 20)
sourceMap["赵"] = 90
sourceMap["钱"] = 100
sourceMap["孙"] = 60 for k, v := range sourceMap {
fmt.Println(k, v)
}
for k := range sourceMap {
fmt.Println(k)
}
for _, m := range sourceMap {
fmt.Println(m) }
}

delete()函数删除键值对

元素为map类型的切片

这个可以理解为在切片里面,各个元素得类型是map。

例如:

var a = make([]map[string]int,3)

值为切片类型的map

这个可以理解为在map函数里面key值是切片。

例如:

var a1 = make(map[string][]int,3)

函数

函数.最重要的一部分

函数定义

func 函数名(参数)(返回值){
函数体
}

example:

func TestFunction(x int,y,int)int{
return x + y
}

对于参数部分如果两个参数类型是一样的可以简化

func TestFunction(x,y int)int{
return x + y
}

可变参数

可变参数就是参数数量不固定,参考数组...

返回值

Go语言中函数支持多返回值,函数如果有多个返回值时必须用()将所有返回值包裹起来。

func calc(x, y int) (int, int) {
sum := x + y
sub := x - y
return sum, sub
}

返回值命名

函数定义时可以给返回值命名,并在函数体中直接使用这些变量,最后通过return关键字返回。

例如:

func calc(x, y int) (sum, sub int) {
sum = x + y
sub = x - y
return
}

返回值补充

当我们的一个函数返回值类型为slice时,nil可以看做是一个有效的slice,没必要显示返回一个长度为0的切片。

func someFunc(x string) []int {
if x == "" {
return nil // 没必要返回[]int{}
}
...
}

全局变量

在函数外定义的变量,函数内可以访问到全局变量

局部变量

在函数内定义的变量,只能在函数内访问得到。

注意:

如果局部变量和全局变量成名,有限访问局部变量。

定义函数类型

type 函数类型 func(int ,int) int

函数作为参数

package main

import "fmt"

func add(x, y int) int {
return x + y } func calc(x, y int, op func(int, int) int) int {
return op(x, y)
}
func main() {
ret2 := calc(10, 20, add)
fmt.Println(ret2) }

函数作为返回值

func do(s string) (func(int, int) int, error) {
switch s {
case "+":
return add, nil
case "-":
return sub, nil
default:
err := errors.New("无法识别的操作符")
return nil, err
}
}

匿名函数

匿名函数就是没有名字的函数,可以把函数赋值给变量,也可以把函数作为返回值。

func(参数)(返回值){
函数体 }

匿名函数没有办法像普通函数那样子调用,他需要保存在某一个变量中(就是赋值),然后在执行。

package main

import "fmt"

func test() {
func () {
fmt.Println("匿 名 函 数")
}()
}
func main() {
test()
}

匿名函数执行:

func test() {
func () {
fmt.Println("匿 名 函 数")
}()//在后面加上括号就相当于执行
}

或者赋值:

package main

import "fmt"

func test() func() {
return func() {
fmt.Println("匿 名 函 数")
}
}
func main() {
r := test()
r() }

闭包

闭包指的是一个函数和与其相关的引用环境组合而成的实体。简单来说,闭包=函数+引用环境

package main

import "fmt"

//闭包简单示例  //闭包概念 闭包=函数+外层变量的引用

func test() func() {
name := "A2rcher"
return func() {
fmt.Println("匿 名 函 数",name) // 如果在匿名函数中找不到调用的变量,他就会向外层去找
} //这个外层变量并不是全局变量,而是函数test()中的局部变量
}
func main() {
r := test() // r引用了函数test()中的变量还有匿名函数 ,可以说r此时就是一个闭包
r() }

闭包还可以这么写(比较典型的一个例子)

package main

import "fmt"

//闭包简单示例  //闭包概念 闭包=函数+外层变量的引用

func test(name string) func() {

	return func() {
fmt.Println("匿 名 函 数", name)
}
}
func main() {
r := test("A2rcher")
r() }

example:

两个很经典的例子 [参考博客](Go语言基础之函数 | 李文周的博客 (liwenzhou.com))

panic & recover & defer

panic/recover:可以理解为异常处理模式(但是Go语言中并没有异常处理机制,只是这样方便理解),

package main

import "fmt"

//panic and recover

func a() {
fmt.Println("func is a")
} //recover必须配合defer使用,而且defer一定要在panic前定义。
func b() {
defer func() {
err := recover()
if err != nil { //如果err不等于nil,说明这个程序出错
fmt.Println("func b is err ")
}
}()
panic("func is b")
} func c() {
fmt.Println("func is c")
} func main() {
a()
b()
c() }

程序运行期间funcB中引发了panic导致程序崩溃,异常退出了。这个时候我们就可以通过recover将程序恢复回来,继续往后执行。

内置函数

内置函数 介绍
close 主要用来关闭channel
len 用来求长度,比如string、array、slice、map、channel
new 用来分配内存,主要用来分配值类型,比如int、struct。返回的是指针
make 用来分配内存,主要用来分配引用类型,比如chan、map、slice
append 用来追加元素到数组、slice中
panic和recover 用来做错误处理

指针

Go语言中指针没有偏移跟运算,只需要搞清楚三个概念和记住两个符号:指针地址,指针类型,指针取值,&(取地址)和*(根据地址取值)。。

贴个链接吧,大佬还是大佬

结构体

类型别名和自定义类型

type定义关键字类型

type myInt int
//将myInt定义成int类型

结构体定义

type 类型名 struct{
字段名 字段类型
字段名 字段类型
...
}

由于Go语言不是面向对象编程语言,是一个面向接口的变成语言,所以他本身不想java那样有多态继承等关系,在Go语言中通过struct来实现面向对象的。(struct YYDS!)

  • 类型名:标识自定义结构体的名称,在同一个包内不能重复。
  • 字段名:表示结构体字段名。结构体中的字段名必须唯一。
  • 字段类型:表示结构体字段的具体类型。

很简单的例子:

type Person struct{
name string
address string
age int
sex string
}

自定义一个Person类型,他有name,address,age,sex四个字段分别代表个自内容。如果我要使用Person中某一个字段,我可以直接调用Person就行了。

结构体实例化

结构体实例化后才可以分配内存使用(实例化后才可以使用自定义类型)

由于结构体本身就是一共类型,所以在声明的时候可以像声明变量一样声明结构体

var 结构体实例 结构体类型

example:

package main

import "fmt"

type Person struct {
name string
age int
} func main() { var p1 Person
//通过.来访问结构体的字段(成员变量),例如p1.name和p1.age等。
p1.name = "A2rcher"
p1.age = 20 fmt.Println(p1)
}

匿名结构体

匿名结构体是用来处理一些临时的数据,比如说我现在A,B两个函数,但是我临时需要使用c数据,这个时候可以用到匿名结构体。

package main

import "fmt"

type Person struct {
name string
age int
} func main() { var p1 Person
p1.name = "A2rcher"
p1.age = 20 var user struct {
Name string `json:"name"`
Age int `json:"age"`
}
user.Age = 30
user.Name = "emo" fmt.Println(p1)
fmt.Println(user) }

指针类型结构体

指针类型结构体是绝大部分情况下用到的,可以通过new关键字对结构体进行实例化得到结构体的地址。(new跟make的区别以及使用的场景参考函数中的内置函数以及指针部分)

方法和接收者

接口

并发

Go语言基础知识总结(持续中)的更多相关文章

  1. OC语言基础知识

    OC语言基础知识 一.面向对象 OC语言是面向对象的,c语言是面向过程的,面向对象和面向过程只是解决问题的两种思考方式,面向过程关注的是解决问题涉及的步骤,面向对象关注的是设计能够实现解决问题所需功能 ...

  2. 李洪强iOS开发之OC语言基础知识

    OC语言基础知识 一.面向对象 OC语言是面向对象的,c语言是面向过程的,面向对象和面向过程只是解决问题的两种思考方式,面向过程关注的是解决问题涉及的步骤,面向对象关注的是设计能够实现解决问题所需功能 ...

  3. Golang 入门系列(三)Go语言基础知识汇总

    前面已经了 Go 环境的配置和初学Go时,容易遇到的坑,大家可以请查看前面的文章 https://www.cnblogs.com/zhangweizhong/category/1275863.html ...

  4. ios开发学习笔记001-C语言基础知识

    先来学习一下C语言基础知识,总结如下: 在xcode下编写代码. 1.编写代码 2.编译:cc –c 文件名.c 编译成功会生成一个 .o的目标文件 3.链接:把目标文件.o和系统自带的库合并在一起, ...

  5. C语言基础知识-数组和字符串

    C语言基础知识-数组和字符串 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.数组概述 在程序设计中,为了方便处理数据把具有相同类型的若干变量按有序形式组织起来的方式我们称为数组 ...

  6. C语言基础知识-程序流程结构

    C语言基础知识-程序流程结构 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.概述 C语言支持最基本的三种程序运行结构:顺序结构,选择结构,循环结构. 顺序结构:程序按顺序执行, ...

  7. C语言基础知识-数据类型

    C语言基础知识-数据类型 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.常量与变量 1>.关键字 C的关键字共有32个. >.数据类型关键字(12个) char,s ...

  8. C语言基础知识-运算符与表达式

    C语言基础知识-运算符与表达式 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.常用运算符分类 1>.算术运算符 用于处理四则运算. 2>.赋值运算符 用于将表达式的 ...

  9. 重拾C语言基础知识

    从实习到工作两年多的时间了,虽然感觉学到了很多知识,但是事实上却将立足之本的基础知识给忘了个精光.也许跟自己没有出去找工作有关,没有好好的将C语言的基础牢牢掌握. 从现在开始吧!好好的重温基础,做一名 ...

随机推荐

  1. 机械革命z2安装ubuntu20

    为了性能买了个游戏本机械革命z2,但还是想用上linux,身为程序员习惯了linux的开发环境有点离不开.但是之前尝试安装deepin或者linux都失败了,一是N卡条件下安装过程和安装之后的显示有问 ...

  2. JAVA实现按列表中元素的时间字段排序

    JAVA代码实现按列表中元素的时间字段排序 导语: 工作中遇到一个问题,调用第三方接口返回的数据没有按时间倒序排列,测试说要加,然后在网上找到一个解决办法,这里记录一下 需求: 如下图列表,按生日进行 ...

  3. 通过浏览器运行cmd命令、启动steam

    我们先来看看实现起来的效果,我们在浏览器中输入ping so.com 试试打开计算器.启动steam 要实现这个效果其实用到了浏览器自定义协议,我们可以通过自定义协议打开wechat.扣扣.emali ...

  4. 虚拟机安装Windows7旗舰版-超详细图文

    虚拟机安装Windows7旗舰版 ----就是想弄一个自己用的CTF+渗透测试的工具集成系统,本来想着用真实机弄就好了,但还是出于安全的考虑,还是再装个虚拟机吧~ 1.先到MSDN找好安装包:http ...

  5. jenkins在aws eks中的CI/CD及slave

    本文档不讲解jenkins的基础用法,主要讲解配合k8s的插件,和pipeline的用途和k8s ci/cd的流程. 以及部署在k8s集群内和集群外的注意事项. 1.准备工作 以下在整个CI/CD流程 ...

  6. 12.10File类

    要点提示:File类包含了获得一个文件/目录的属性,以及对文件/目录进行改名和删除的方法. 在文件系统中,每个文件都存放在一个目录下.绝对文件名,是由文件名和它的完整路径以及驱动器字母组成.例如,c: ...

  7. 详解 MD5 信息摘要算法

    对于软件研发人员来说 MD5 不是一个陌生的词汇,平时的软件研发中,经常使用 MD5 校验消息是否被篡改.验证文件完整性,甚至将MD5当作加密算法使用. MD5虽不陌生,但不是所有研发人员都了解其算法 ...

  8. Springboot quartz集群(3) — 多节点发送邮件

    本期将提供quartz集群能力 集群案例分析: 上一期的邮件发送功能,若在服务需要部署多节点,但定时任务不支持集群,因此,多节点定时任务势必会同时运行, 若向用户发送邮件通知,这种情况下会向用户发送两 ...

  9. MySQL参数配置

    参数名称 参数说明 缺省值 最低版本要求 user 数据库用户名(用于连接数据库) 所有版本 passWord 用户密码(用于连接数据库) 所有版本 useUnicode 是否使用Unicode字符集 ...

  10. log4j和log4j2的配置部分

    log4j和log4j2的功能及形式对比 http://blog.csdn.net/fangaohua200/article/details/53561718 log4j2的proptise配置 ht ...