首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >golang基础(一)

golang基础(一)

作者头像
阿dai学长
发布于 2020-03-31 03:07:23
发布于 2020-03-31 03:07:23
53000
代码可运行
举报
文章被收录于专栏:阿dai_linux阿dai_linux
运行总次数:0
代码可运行

Go编程结构

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
// 当前程序的包名
package main

// 导入其他的包
// import "fmt"

// 导入其他的包,并设置别名
import std "fmt"

// 定义常量
const PI  = 3.14

// 全局变量的声明与赋值
var name  = "gopher"

// 一般类型声明:为类型设置别名
type newType int

// 结构的声明
type gopher string{}

// 接口的声明
type golang interface {}

// 由 main 函数作为程序入口点启动
func main() {
   std.Println("Hello world!")
}

Tips:

  • go程序中导入的包如果在程序中未使用,程序会报错,即不能 import 不使用的包;
  • go中可以使用 . 作为包的别名,不过,尽量不要使用,避免降低代码可读性;
  • go中的 privatepublic 是通过大小写来实现的,以大写字母开头的变量、函数等是public型,以小写字母开头的是private型

数据类型与变量

类型和变量都能批量声明,变量组只能用于全局变量声明,不能在函数体重使用。

数据类型

  • 布尔型:bool
  • 整型:int/uint
  • 8位整型:int8/uint8
  • 字节型:byte(unit8别名)
  • 16位整型:int16/uint16
  • 32位整型:int32/uint32
  • 64位整型:int64/uint64
  • 浮点型:float32/float64
  • 复数:complex64/complex128
  • 其他值类型:
    • array、struct、string
  • 引用类型:
    • slice、map、chan
  • 接口类型:interface
  • 函数类型:func

变量

单个变量的声明与赋值

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
// 变量的声明
var a int

// 变量的赋值
a = 123

// 声明的同时赋值
var a int = 123

多个变量的声明与赋值

  • 全局变量的声明不可以省略 var ,但可以用并行方式
  • 全局变量的声明可以使用 var() 的方式进行简写
  • 局部变量不可以使用 var() 的方式简写,只能使用并行方式
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
// 多个变量的声明
var a, b, c int

// 多个变量的复制
a, b, c, = 111, 222,333

// 多个变量声明的同时赋值
var d, e, f int = 444, 555, 666

// 省略变量类型,由系统推断
var i, j, k = 777, 888, 999

// 多个变量声明与赋值的最简写法
m, n, o := 1, 2, 3

var (
	// 使用常规方式
	aaa = "hello"
	// 使用并行方式
	sss, bbb = 1, 2
)

// 函数体内只能使用并行方式声明多个变量
func main() {
	var x, y, z int = 444, 555, 666
  // var aa, _, bb, cc = 11, 22, 33, 44  // _ 为空白符号,即忽略对应位置的值
}

类型转换

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
// 只能在相互兼容的类型之间转换
func main() {
   var a float32 = 1.1
   b := int(a)
   fmt.Println(a)
   fmt.Println(b)
}

练习:计算机存储单位的枚举

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
const (
   B float64 = 1 << (iota * 10)
   KB
   MB
   GB
   TB
   PB
)

func main() {
   fmt.Println(B)
   fmt.Println(KB)
   fmt.Println(MB)
   fmt.Println(GB)
   fmt.Println(TB)
   fmt.Println(PB)
}

补充内容

go保留了指针,但不支持指针运算以及 -> 运算符,而直接采用 . 选择符来操作指针目标对象的成员。

  • 操作符 & 取变量地址,使用 * 通过指针间接访问目标对象
  • 默认值为 nil,而非 NULL

go语言中(递增、递减),++-- 是作为语句而并不是作为表达式(即,只能作为单独的语句存在)。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
// 指针
func main() {
	a := 1
	var p *int = &a  // 指针 p 指向变量 a 的地址
	fmt.Println(p)  // 打印指针
	fmt.Println(*p)  // 打印指针对应的目标对象
}

// ++ 和 --
func main() {
	// a := a++  // 不允许这样
	a := 1
	a++
	var p *int = &a
	fmt.Println(p)
	fmt.Println(*p)
}

go控制语句

判断语句 if

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
func main() {
   a := 10
   if a, b := 1, 3; a > 0 {
      fmt.Println(a)
      fmt.Println(b)
   }
   fmt.Println(a)
}

循环语句 for

go语言中只有 for 循环。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
// 普通 for 循环
func main() {
   a := 1
   for {
      a++
      if a > 3 {
         break
      }
      fmt.Println(a)

   }
   fmt.Println("Over!")
}

// for 循环本身带条件
func main() {
	a := 1
	for a <= 3 {
		a++
		fmt.Println(a)
	}
	fmt.Println("Over!")
}

// 经典用法:计数器(i)
func main() {
	a := 1
	for i := 0; i <= 3; i++ {
		a++
		fmt.Println(a)
	}
	fmt.Println("Over!")
}

选择语句 switch

默认满足某个 case 后自动 break,如果想继续执行后面的 case,需要使用 fallthrough 语句。

类似 python 中的 if...elif...else...

switch 中有变量 swithc a {},则case中默认使用该变量创建表达式( case 0: );如果switch中没有变量 switch {},则需要在case中使用变量创建表达式(case a==0:)。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
// 普通用法
func main() {
   a := 1
   switch a {
   case 0:
      fmt.Println("a=0")
   case 1:
      fmt.Println("a=1")
   default:
      fmt.Println("None")
   }
}

// fallthrough
func main() {
	a := 1
	switch {
	case a <= 0:
		fmt.Println("a=0")
	case a >= 1:
		fmt.Println("a=1")
		fallthrough
	default:
		fmt.Println("None")
	}
}

// 带一个初始化语句
func main() {
	switch a := 1; {
	case a >= 10:
		fmt.Println("a=0")
	case a >= 1:
		fmt.Println("a=1")
		fallthrough
	default:
		fmt.Println("None")
	}
}

跳转语句 goto,break,continue 和 标签

跳转语句都可以配合标签使用。标签区分大小写。

goto用于调整执行位置;break和continue配合标签可以跳出多层循环。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
// 跳出 LABEL1 循环
func main() {
LABEL1:
   for {
      for i := 0; i < 10; i++ {
         if i > 3 {
            break LABEL1
         }
         fmt.Println(i)
      }
   }
   fmt.Println("Over")
}

// continue 本身可以是一个无限循环;但是 continue 对应的标签必须有限循环,不然会造成死循环;
func main() {
LABEL1:
	for i := 0; i < 10; i++ { // 有限循环,即 LABEL1 对应有限循环
		fmt.Println(i)
		for {  // 无限循环
			continue LABEL1 // 有限循环标签
			fmt.Println("???")
		}
	}
	fmt.Println("Over")
}

练习:for + switch + if

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
func main() {
   a := 1
   for {
      switch {
      case a <= 5:
         fmt.Println("a=", a)
      case a > 5 && a <= 10:
         fmt.Println("a=", a)
         fallthrough
      default:
         fmt.Println("None")
      }
      a++
      if a > 10 {
         fmt.Println("Over...", "a=", a)
         break
      }
   }
}

Tips: goto 结合标签使用的时候,标签放在 goto 语句的后面,避免造成死循环。

数组:array

  • 定义数组格式:var <varName> [n]<type>n>=0
  • 数组之间可以用 ==!= 比较,但是不可以使用 <>
  • 可以使用new来创建数组,此方法返回一个指向数组的指针,但是可以通过指针对数组进行操作
  • 如果不值得数组的长度,可以使用 [...] 来让系统自动计算数组长度(注意:该方法只能用于顶级数组)
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
// 普通
func main() {
	var a [2]int
  fmt.Println(a)
	a[0] = 5
	a[1] = 6
	fmt.Println(a)
}

// 最简方式
func main() {
	a := [2]int{7, 8}
	fmt.Println(a)
}

// 为数组的某一位赋值
func main() {
	a := [2]int{7, 8}
	fmt.Println(a)
	b := [10]int{5: 5}
	fmt.Println(b)
}

// 数组间的比较
func main() {
	a := [2]int{1, 2}
	b := [2]int{1, 2}
	fmt.Println("a=", a)
	fmt.Println("b=", b)
	fmt.Println(a == b)
	fmt.Println(a != b)
}

// 使用new方法创建数组
func main() {
	a := [10]int{}
	a[1] = 2
	fmt.Println(a)

	p := new([10]int)
	p[1] = 2  // 通过指针对数组中单个元素进行操作
	fmt.Println(p)
}

指向数组的指针 和 指针数组

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
func main() {
   a := [10]int{9, 1}
   var p *[10]int = &a // 指向数组的指针
   fmt.Println(p)

   x, y := 1, 2
   b := [...]*int{&x, &y} // 指针数组
   fmt.Println(b)
}

在go语言中数组是值类型。

多维数组:数组中嵌套数组

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
func main() {
   a := [2][3]int{ // 含义是:数组a包含2个元素,每个元素为长度为3的int型数组
      {1, 1, 1},
      {2, 2, 2}}

   fmt.Println(a)
}

go语言实现冒泡排序

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
func main() {
   a := [...]int{5, 3, 6, 7, 9}
   fmt.Println(a)

   num := len(a)
   for i := 0; i < num; i++ {
      for j := i + 1; j < num; j++ {
         if a[i] < a[j] {
            temp := a[i]
            a[i] = a[j]
            a[j] = temp
         }
      }
   }
   fmt.Println(a)
}

切片:slice

  • 切片本身不是数组,它指向的是一个数组
  • 一般使用 make() 创建
  • 用于切片的两个函数:
    • len():获取切片长度
    • cap():获取切片容量
  • 如果多个切片(slice)指向相同底层数组,其中一个值的改变会影响全部
  • 创建切片的格式:make([]Type, len, cap)
    • len:表示切片当前实际长度
    • cap:容量,表示当前切片超出len后的最大容量,用于预分配资源(提升效率)
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
// 
func main() {
	var s1 []int // 声明slice,结果为一个空的slice
	fmt.Println(s1)

	a := [10]int{1, 2, 3, 4, 5, 6, 7, 8, 9}
  s2 := a[0:5] // 从已有数组中取值
	fmt.Println(s2)
	s3 := a[5:]
	fmt.Println(s3)
}

// make中的 len 和 cap
func main() {
	s1 := make([]int, 5, 10)
	fmt.Println(s1)
	fmt.Println(len(s1), cap(s1))
}

reslice:从一个slice中获取新的slice

  • reslice时索引以被slice的切片为准
  • 索引不可超过被slice的切片的容量cap()值
  • 索引越界不会导致底层数组重新分配,而是引发错误

slice与底层数组的对应关系:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
func main() {
   a := []byte{'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n'}
   fmt.Println("================= aa ===================")
   fmt.Println("a=", string(a))
   fmt.Println("len(a)=", len(a), "cap(a)=", cap(a))
   fmt.Println("================= sa ===================")
   sa := a[2:5]
   fmt.Println("sa=", string(sa))
   fmt.Println("len(sa)=", len(sa), "cap(sa)=", cap(sa))
   fmt.Println("================= sb ===================")
   sb := sa[3:5]
   fmt.Println("sb=", string(sb))
   fmt.Println("len(sb)=", len(sb), "cap(sb)=", cap(sb))
}

append

  • 可以在slice尾部追加元素
  • 可以将一个slice追加到另一个slice的尾部
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
func main() {
	s1 := make([]int, 3, 6)
	fmt.Printf("%p %v\n", s1, s1)
	s1 = append(s1, 1, 2, 3)  // 未超出原始slice容量时,内存地址不变
	fmt.Printf("%p %v\n", s1, s1)
	s1 = append(s1, 1, 2, 3)  // 超出原始slice容量时,会重新分配内存地址
	fmt.Printf("%p %v\n", s1, s1)
}


func main() {
	a := []int{1, 2, 3, 4, 5}
	s1 := a[2:5]
	s2 := a[1:3]
	fmt.Println(s1, s2) // 此时 s1,s2 共用 a[2]
	s1[0] = 9           // 多个切片(slice)指向相同底层数组,其中一个值的改变会影响全部
	fmt.Println(s1, s2)
	fmt.Println(a)
	s2 = append(s2, 1, 2, 3, 4, 5, 6, 7)
	s1[0] = 10
	fmt.Println(s1, s2) // 超出原始切片(s1)容量的部分不受影响,因为超出原始切片容量后,已分配新的内存地址
	fmt.Println(a)
}

copy

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
// copy时,以短的slice中元素长度为准进行copy
func main() {
   s1 := []int{1, 2, 3, 4, 5, 6}
   s2 := []int{7, 8, 9}
   fmt.Println(s1, s2)
   copy(s1, s2)
   fmt.Println("new:: ", s1, s2)

   s3 := []int{1, 2, 3, 4, 5, 6}
   s4 := []int{7, 8, 9}
   fmt.Println(s3, s4)
   copy(s4, s3)
   fmt.Println("new:: ", s3, s4)
}

// 拷贝到目标切片的指定位置
func main() {
	s1 := []int{1, 2, 3, 4, 5, 6}
	s2 := []int{7, 8, 9}
	fmt.Println(s1, s2)
	copy(s1[2:5], s2) 
	fmt.Println("new:: ", s1, s2)
}
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
华为ensp中USG6000V防火墙双机热备VRRP+HRP原理及配置
华为防火墙双机热备的工作原理是通过两台防火墙设备之间定期发送心跳报文来判断对方的状态。如果主用防火墙出现故障,备用防火墙会收到主用防火墙停止发送心跳报文的消息,然后会自动切换为新的主用防火墙。
神秘泣男子
2024/06/03
3.6K1
华为ensp中USG6000V防火墙双机热备VRRP+HRP原理及配置
三种知名的第一跳冗余协议(FHRP):HSRP、VRRP和GLBP
在计算机网络中,可靠性和高可用性是至关重要的。为了确保网络中的连续性和冗余,网络管理员经常使用冗余协议。第一跳冗余协议(First Hop Redundancy Protocol,FHRP)是一种网络协议,用于提供在默认网关故障时的备用路由。
网络技术联盟站
2023/07/14
6270
三种知名的第一跳冗余协议(FHRP):HSRP、VRRP和GLBP
【详解】Nginx+keepalived双机热备
在互联网的高可用性服务中,单一的服务节点往往无法满足业务对稳定性和可用性的要求。双机热备是一种常见的高可用性解决方案,它通过两台服务器同时运行相同的服务,并使用 Keepalived 来实现故障转移,确保在主服务器发生故障时,备服务器能够立即接管服务,从而保证服务的连续性。本文将详细介绍如何在 Nginx 环境中部署双机热备方案。
大盘鸡拌面
2025/01/01
3140
解决网关单点故障三剑客:VRRP、HSRP、GLBP
通常情况下,在终端设备进入网络前,都会有一个 Router 充当网络,作为第一跳的网络地址。但假设路由器发生故障,此时终端设备就无法再接入互联网。
网络技术联盟站
2023/03/01
1.2K0
解决网关单点故障三剑客:VRRP、HSRP、GLBP
Nginx系列(7) —— Nginx配置高可用集群
CAP原则又称CAP定理,指的是在一个分布式系统中,一致性(Consistency)、可用性(Availability)、分区容错性(Partition tolerance)。CAP 原则指的是,这三个要素最多只能同时实现两点,不可能三者兼顾。
求和小熊猫
2020/11/25
1.7K0
核心交换机的四种关键技术:链路聚合、冗余、堆叠和热备份,真简单!
当涉及到核心交换机的关键技术,如链路聚合、冗余、堆叠和热备份时,下面更详细地介绍每个技术的工作原理和优势。
网络技术联盟站
2023/06/01
10K0
核心交换机的四种关键技术:链路聚合、冗余、堆叠和热备份,真简单!
图解网络:什么是网关负载均衡协议GLBP?
充当 GLBP 组的 ARP 响应者,这些响应由 AVG 分配的 GLBP 组成员的虚拟 MAC 地址组成。
网络技术联盟站
2022/07/04
1.9K0
图解网络:什么是网关负载均衡协议GLBP?
玩转企业集群运维管理系列(十):企业集群高可用软件 Keepalived 详解
Keepalived 是 Linux 下的一个免费的、轻量级的高可用解决方案。是一个由C语言编写的路由软件,主要目标是为 Linux 系统和基于 Linux 的基础架构提供简单而强大的负载平衡和高可用性。
民工哥
2023/12/12
6470
玩转企业集群运维管理系列(十):企业集群高可用软件 Keepalived 详解
什么是双机热备技术?华为和思科如何实现双机热备?
在当今高度依赖网络的时代,网络设备的高可用性和可靠性变得尤为重要。网络设备的故障可能导致服务中断、数据丢失以及生产力下降等问题。为了应对这些挑战,一种常见的解决方案是使用双机热备(High Availability, HA)技术。本文将详细介绍网络设备双机热备的原理、应用场景、优势以及在华为设备和思科设备的解决方案。
网络技术联盟站
2023/06/09
4.7K0
什么是双机热备技术?华为和思科如何实现双机热备?
Keepalived+LVS+DR结合实现高可用群集
Keepalived 是一个用于实现高可用性。它主要用于确保服务的连续性,防止单点故障,通常应用于负载均衡和故障转移场景。
神秘泣男子
2025/01/21
2040
Keepalived+LVS+DR结合实现高可用群集
万字长文带你从 0 学习 Keepalived
负载均衡器(Load Balancer, LB )是一组能够将IP数据流以负载均衡形式转发到多台物理服务器的集成软件。有硬件负载均衡器和软件负载均衡器之分,硬件负载均衡器主要是在访问网络和服务器之间配置物理负载均衡设备,客户端对物理服务器的访问请求首先会抵达负载均衡设备,然后再由负载均衡设备根据一定的负载算法转发到后端服务器。相比而言,软件负载均衡器不需要特定的物理设备,只需在相应的操作系统上部署具有负载均衡功能的软件即可。
小小科
2018/07/31
7790
万字长文带你从 0 学习 Keepalived
你是我生命里的 VRRP,是我最坚定的主心骨,无论风雨多大,只要有你在,我就知道爱不会迷失方向,未来永远充满希望 。——基于华为ENSP的链路聚合和VRRP全面深入剖析
盛透侧视攻城狮
2025/02/14
3040
你是我生命里的 VRRP,是我最坚定的主心骨,无论风雨多大,只要有你在,我就知道爱不会迷失方向,未来永远充满希望 。——基于华为ENSP的链路聚合和VRRP全面深入剖析
043. 基于 VIP 的 Keepalived 高可用架构讲解
1. Keepalived 简介 ---- 1. keepalived 的作用 Keepalived 的作用是检测服务器的状态。如果有一台 web 服务器宕机,或工作出现故障,Keepalived 将检测到,并将有故障的服务器从系统中剔除,同时使用其他服务器代替该服务器的工作,当服务器工作正常后 Keepalived 自动将服务器加载到服务器群中,这些工作全部自动完成,不需要人工干涉,需要人工做的只是修复故障的服务器。 2. Keepalived 的特性 配置文件简单:配置文件比较简单,可通过简单配置实现高
山海散人
2021/03/03
1.9K0
043. 基于 VIP 的 Keepalived 高可用架构讲解
图解网络:什么是热备份路由器协议HSRP?
HSRP是思科私有协议,那么它有哪些特别好使的功能,原理是啥,和VRRP的区别是怎样的?
网络技术联盟站
2022/07/03
1.4K0
图解网络:什么是热备份路由器协议HSRP?
虚拟ip的概念_虚拟化的概念
要是单讲解虚拟 IP,理解起来很困难,所以干脆把 动态 IP 、固定 IP 、实体 IP 与虚拟 IP都讲解一下,加深理解和知识扩展
全栈程序员站长
2022/11/01
1.8K0
虚拟ip的概念_虚拟化的概念
图解网络:什么是虚拟路由器冗余协议 VRRP?
VRRP是一种比较常用容错协议,可以提高网络的可靠性,今天瑞哥和大家详细的介绍一下VRRP协议。
网络技术联盟站
2023/03/05
1.1K0
图解网络:什么是虚拟路由器冗余协议 VRRP?
图解网络:什么是虚拟路由器冗余协议 VRRP?
VRRP是一种比较常用容错协议,可以提高网络的可靠性,今天瑞哥和大家详细的介绍一下VRRP协议。
网络技术联盟站
2022/07/02
1.6K0
图解网络:什么是虚拟路由器冗余协议 VRRP?
nginx高可用方案及部署文档
Nginx是一款非常流行的高性能Web服务器,也可以作为负载均衡器来提供高可用性。在本文中,我将介绍一种基于Nginx的高可用方案,同时提供一份详细的部署文档。
堕落飞鸟
2023/03/27
1.5K0
华为ensp中vrrp虚拟路由器冗余协议 原理及配置命令
VRRP(Virtual Router Redundancy Protocol,虚拟路由器冗余协议)是一种网络协议,用于提供冗余的网关功能,确保网络中的设备能够自动切换到备用网关,从而实现网络的高可用性。在华为的企业网络模拟平台(ENSP)中,VRRP可以用于模拟和配置这种冗余功能。
神秘泣男子
2024/06/03
1.6K0
华为ensp中vrrp虚拟路由器冗余协议 原理及配置命令
01 . Keepalived原理使用和配置
1 . 添加冗余的心跳线,例如:双线条线(心跳线也HA),尽量减少“裂脑”发生几率;
iginkgo18
2020/09/27
1.7K0
推荐阅读
相关推荐
华为ensp中USG6000V防火墙双机热备VRRP+HRP原理及配置
更多 >
交个朋友
加入腾讯云官网粉丝站
蹲全网底价单品 享第一手活动信息
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档