通过示例学习-Go-语言-2023-十三-
通过示例学习 Go 语言 2023(十三)
Go 中的 For 循环(Golang)
这是 Golang 综合教程系列的第十章。请参阅此链接以获取该系列的其他章节 – Golang 综合教程系列
下一个教程 – For Range 循环
前一个教程 – 常量
现在让我们查看当前教程。以下是当前教程的目录。
概述
在循环方面,Golang 具有:
-
for 循环
-
for-range 循环
在本教程中,我们将只学习 for 循环。while 循环在 Go 中缺失,但可以使用 for 循环来实现 while 循环,稍后我们将在本教程中看到。
for 循环在 GO 中基本上有三个部分,如下格式所示
-
初始化部分
-
条件部分
-
后置部分
for init_part; condition_part; post_part {
...
}
以下是三个部分的执行顺序:
-
初始化部分在第一次迭代前首先执行。
-
条件部分在每次迭代前执行。如果条件为假,循环将退出,否则循环将继续迭代。
-
后置部分在每次迭代后执行。之后检查条件,如果为真,则循环继续,否则循环结束。
关于 for 循环需要注意的一些要点:
-
在 for 循环中,括号不是必需的,但主体周围的花括号是必要的。
-
初始化和后置部分是可选的。
-
初始化部分可以是任何带有短声明、函数调用或赋值的语句。如果初始化部分有变量声明,则该变量的作用域仅限于 for 循环内部。
-
后置部分可以是任何语句,但通常包含增量逻辑。后置部分不能包含初始化。如果我们在后置部分添加任何初始化逻辑,编译器将会报错。
示例
简单的 for 循环
package main
import "fmt"
func main() {
for i := 0; i < 5; i++ {
fmt.Println(i)
}
}
输出:
0
1
2
3
4
仅带条件的 for 循环
package main
import "fmt"
func main() {
i := 0
for i < 5 {
fmt.Println(i)
i++
}
}
输出:
0
1
2
3
4
无限循环
package main
import (
"fmt"
"time"
)
func main() {
i := 0
for {
fmt.Println(i)
i++
time.Sleep(time.Second * 1)
}
}
输出: 上述程序打印一个无限循环
0
1
2
3
4
5
.
.
For 循环中的中断语句
break 语句帮助退出 for 循环。循环内 break 后的语句不被执行。
package main
import (
"fmt"
)
func main() {
i := 0
for {
fmt.Println(i)
i++
if i >= 5 {
break
}
}
}
输出:
0
1
2
3
4
For 循环中的继续语句
continue 语句帮助跳过 for 循环的当前迭代。continue 后的语句不被执行,执行将重新回到开始,并进行下一次迭代。使用场景是当你只想对 for 循环的某些元素进行操作时。
让我们看看下面程序的例子,我们只想打印非 3 的倍数。
package main
import "fmt"
func main() {
for i := 1; i < 10; i++ {
if i%3 == 0 {
continue
}
fmt.Println(i)
}
}
输出:
1
2
4
5
7
8
10
嵌套 For 循环
for 循环也可以嵌套。请看下面的例子。
package main
import "fmt"
func main() {
for i := 0; i < 3; i++ {
fmt.Printf("Outer loop iteration %d\n", i)
for j := 0; j < 2; j++ {
fmt.Printf("i= %d j=%d\n", i, j)
}
}
}
输出:
Outer loop iteration 0
i= 0 j=0
i= 0 j=1
Outer loop iteration 1
i= 1 j=0
i= 1 j=1
Outer loop iteration 2
i= 2 j=0
i= 2 j=1
初始化部分中的函数调用和赋值
下面的代码是一个示例,我们也可以在初始化部分进行函数调用或赋值。
package main
import "fmt"
func main() {
i := 1
//Function call in the init part in for loop
for test(); i < 3; i++ {
fmt.Println(i)
}
//Assignment in the init part in for loop
for i = 2; i < 3; i++ {
fmt.Println(i)
}
}
func test() {
fmt.Println("In test function")
}
输出
In test function
1
2
2
使用 for 循环实现 while 循环
Go 没有while关键字。相反,它只有for关键字。然而,for关键字可以用来模拟与while相同的功能。
如果可以跳过初始化部分和增量部分,则可以将for循环实现为与while相同的行为。以下是一个示例:
package main
import "fmt"
func main() {
i := 1
for i <= 5 {
fmt.Println(i)
i++
}
}
输出:
1
2
3
4
5
结论
这都是关于 golang 中的 for 循环。请在评论中分享反馈/改进/错误。
下一教程 – 范围循环
上一篇教程 – 常量
Go(Golang)中的通道范围循环
范围循环可以用于从通道接收数据,直到它被关闭。请注意,范围循环将持续从通道接收数据,退出的唯一方式是关闭通道。
让我们看看一个程序来理解它。
package main
import (
"fmt"
"time"
)
func main() {
ch := make(chan int)
ch <- 2
ch <- 2
ch <- 2
close(ch)
sum(ch)
time.Sleep(time.Second * 1)
}
func sum(ch chan int) {
sum := 0
for val := range ch {
sum += val
}
fmt.Printf("Sum: %d\n", sum)
}
输出
Sum: 6
在上述程序中,我们创建了一个通道。在主函数中发送三个值到通道,然后关闭了通道。接着我们调用了求和函数,并将通道传递给该函数。在求和函数中,我们对通道进行了一个范围循环。在迭代通道中的所有值后,由于通道已关闭,范围循环将退出。
现在脑海中出现的问题是,如果你在主函数中不关闭一个通道会发生什么。尝试注释掉关闭通道的那一行。现在运行这个程序。它也会输出死锁,因为对于范围循环在求和函数中将永远不会结束。
fatal error: all goroutines are asleep - deadlock!
在 Go(Golang)中格式化消息而不打印。
目录
-
概述
-
示例
概述
fmt 包的 Sprintf 函数可以用来格式化字符串而不打印。它与 Printf 函数类似,唯一的区别在于二者。
-
Printf 格式化并打印消息。
-
Sprintf 仅格式化消息。
以下是 Sprintf 函数的语法。
func Sprintf(format string, a ...interface{}) string
Sprintf 函数根据格式说明符格式化字符串并返回结果字符串。
示例
让我们看一个程序。
package main
import "fmt"
func main() {
formattedMessage := fmt.Sprintf("Name is: %s. Age is: %d", "John", 21)
fmt.Println(formattedMessage)
}
输出
Name is: John. Age is: 21
在上述程序中,fmt.Sprintf 正确格式化消息,而 fmt.Println 用于打印格式化后的消息。
用于布尔值的格式说明符或在 Go(Golang)中打印布尔值。
可以使用不同的格式说明符以布尔或字符串形式打印布尔值。
-
%t 可用于以布尔形式打印。
-
%v 将打印默认字符串。“true”代表真,“false”代表假。
代码:
package main
import "fmt"
func main() {
t := true
f := false
fmt.Printf("%t %t\n", t, f)
fmt.Printf("%v %v\n", t, f)
}
输出
true false
true false
Go(Golang)中的函数闭包
目录
-
概述
-
代码:
-
示例 1
-
示例 2:
-
示例 3:
-
概述
函数闭包只是一个匿名函数,它可以访问在函数外部声明的变量,并且在不同的函数调用之间保留这些变量的当前值。匿名函数是没有名称的函数。
当一个函数在另一个函数内定义时,闭包发生,内层函数可以访问外层函数的变量。
你可以在这里阅读更多关于闭包的内容。
en.wikipedia.org/wiki/Closure_(computer_programming)
代码:
让我们看一个例子。在示例 1 中有三件事需要注意。
-
getModulus 函数返回一个闭包。它被赋值给变量 modulus
-
这个闭包函数可以访问在其主体外定义的 count 变量。
-
count 变量的值在 modulus 函数的不同调用之间得以保留。
示例 1
package main
import (
"fmt"
)
func main() {
modulus := getModulus()
modulus(-1)
modulus(2)
modulus(-5)
}
func getModulus() func(int) int {
count := 0
return func(x int) int {
count = count + 1
fmt.Printf("modulus function called %d times\n", count)
if x < 0 {
x = x * -1
}
return x
}
}
输出:
modulus function called 1 times
modulus function called 2 times
modulus function called 3 times
示例 2:
下面是另一个闭包函数的示例。该函数能够访问 valueOutside 变量。
package main
import "fmt"
func main() {
valueOutside := "somevalue"
func() {
fmt.Println(valueOutside)
}()
}
输出:
somevalue
示例 3:
在下面的示例中,闭包函数能够访问 count 变量及其值,并且该值在不同的函数调用之间得以保留。
package main
import "fmt"
func main() {
count := 0
for i := 1; i <= 5; i++ {
func() {
count++
fmt.Println(count)
}()
}
}
输出
1
2
3
4
5
```*
<!--yml
类别:未分类
日期:2024-10-13 06:16:51
-->
# Go 语言中的函数
> 来源:[`golangbyexample.com/function-golang-complete-guide/`](https://golangbyexample.com/function-golang-complete-guide/)
这是 Go 语言综合教程系列的第八章。有关该系列其他章节,请参考此链接 – [Go 语言综合教程系列](https://golangbyexample.com/golang-comprehensive-tutorial/)
**下一教程** – [常量](https://golangbyexample.com/constant-golang/)
**上一教程** – [所有基本数据类型](https://golangbyexample.com/all-basic-data-types-golang/)
现在让我们来查看当前的教程。以下是当前教程的目录。
目录
**概述**
+ **函数的签名**
+ **调用函数**
+ **函数参数**
+ **返回值**
+ **命名返回值**
+ **函数用法**
+ **泛型用法**
+ **函数作为类型**
+ **函数作为用户定义类型**
+ **函数作为值(或匿名函数)")**
+ **函数的特殊用法**
+ **函数闭包**
+ **高阶函数**
+ **IIF 或立即调用函数**
+ **可变参数函数**
+ **方法**
+ **结论** *# **概述**
函数是一组执行特定任务的语句。在 Go 中,函数是一级变量,可以像其他变量一样传递。
关于函数名称的一些注意事项
+ 函数名称不能以数字开头
+ 函数名称是区分大小写的。因此,sum、Sum、SUM 是不同的函数。
+ 名称以大写字母开头的函数将被导出到其包外,并可以从其他包调用。名称以小写字母开头的函数不会被导出,仅在其包内可见。
# **函数的签名**
```go
func func_name(input_parameters) return_values{
//body
}
Go 语言中的函数
-
使用func关键字声明
-
它有一个名称
-
逗号分隔的零个或多个输入参数
-
逗号分隔的零个或多个返回值
-
函数体
-
可以返回多个值
一个函数的例子。下面的函数是
-
名称为“sum”
-
接受两个 int 类型的参数
-
返回一个 int 类型的单一值
func sum(a int, b int) int {
return a + b
}
调用函数
Go 中的函数可以如下调用
results := sum(2, 3)
调用函数时需要注意的一些要点
-
如果调用的是其他包中的函数,则必须在前面加上包名。另外,请注意,在不同包之间只能调用那些被导出的函数,即名称以大写字母开头的函数。
-
在同一个包内,可以直接使用名称后缀 () 调用函数。
函数参数
-
如上所述,函数可以有零个或多个参数。
-
连续相同类型的类型可以只指定一次。例如,上面的求和函数也可以写成。
func sum(a, b int)
- 在调用函数时会创建所有参数的副本。
返回值
- 如上所述,函数可以有一个或多个返回值。假设有一个函数 sum_avg 返回两个值:和与平均值。多个返回值的示例。
func sum_avg(a, b int) (int, int)
- 按照约定,错误作为函数的最后一个参数返回。示例。
func sum(a, b int) (int, error)
- 在调用函数中收集多个返回值。在下面的示例中。
result, err := sum(2, 3)
命名返回值
Go 函数可以具有命名返回值。对于命名返回值,返回值在函数中不需要初始化。命名变量在签名中指定。没有命名值时,仅指定返回类型。对某些返回值命名也是可以的。对于其他返回值,只能指定类型。
- 见下面的示例:result 是命名返回值。
func sum(a, b int) (result int)
- 对于命名返回值,连续相同类型的类型只能指定一次。
func sum_avg(a, b int) (sum, avg int)
函数用法
-
通用用法
-
函数作为类型
-
函数作为值
函数作为类型与函数作为值之间的区别在于,在类型中我们只使用函数签名,而在函数作为值时则使用签名和主体。让我们详细了解每个内容,以便更清晰。
通用用法
以下是函数一般用法的示例。我们在下面的示例中有一个函数 sum,它接受两个整数作为输入参数并返回它们的和。
package main
import "fmt"
func main() {
res := sum(2, 3)
fmt.Println(res)
}
func sum(a, b int) int {
return a + b
}
输出:
5
函数作为类型
在 Go 中,函数也是一种类型。如果两个函数是同一类型的。
-
它们有相同数量的参数,每个参数的类型相同。
-
它们有相同数量的返回值,并且每个返回值的类型相同。
函数类型在以下情况下非常有用。
-
在上述例子中,我们看到高阶函数的情况。参数和返回类型是通过函数类型来指定的。
-
在 Go 中定义接口的情况下,接口中仅指定函数类型。实现此接口的任何东西都必须定义相同类型的函数。
让我们看一个接口中函数类型的示例。注意接口 shape 只定义了函数的类型。
area() int
getType() string
代码:
package main
import "fmt"
func main() {
var shapes []shape
s := &square{side: 2}
shapes = append(shapes, s)
r := &rectangle{length: 2, breath: 3}
shapes = append(shapes, r)
for _, shape := range shapes {
fmt.Printf("Type: %s, Area %d\n", shape.getType(), shape.area())
}
}
type shape interface {
area() int
getType() string
}
type rectangle struct {
length int
breath int
}
func (r *rectangle) area() int {
return r.length * r.breath
}
func (r *rectangle) getType() string {
return "rectangle"
}
type square struct {
side int
}
func (s *square) area() int {
return s.side * s.side
}
func (s *square) getType() string {
return "square"
}
输出:
Type: square, Area 4
Type: rectangle, Area 6
作为用户定义类型的函数
自定义类型的函数可以使用 type 关键字声明。
package main
import "fmt"
func main() {
areaF := getAreaFunc()
print(3, 4, areaF)
}
type area func(int, int) int
func print(x, y int, a area) {
fmt.Printf("Area is: %d\n", a(x, y))
}
func getAreaFunc() area {
return func(x, y int) int {
return x * y
}
}
输出:
12
作为值的函数(或匿名函数)
Go 语言中的函数是一个一阶变量,因此也可以作为值使用。它也被称为匿名函数,因为函数没有名称,可以被赋值给一个变量并传递。
它们通常用于短期使用或有限功能。请看下面的示例。在这个示例中,变量 max 被赋值为一个函数。由于 max 是由一个没有名称的函数创建的,所以它是一个匿名函数。
package main
import "fmt"
var max = func(a, b int) int {
if a >= b {
return a
}
return b
}
func main() {
res := max(2, 3)
fmt.Println(res)
}
输出:
3
函数的特殊用法
函数闭包
函数闭包就是可以访问在函数外声明的变量,并且在不同函数调用之间保持当前值的匿名函数。我们来看一个例子。在下面的案例中,modulus 函数的不同调用之间 count 的值得以保留。
package main
import (
"fmt"
)
func main() {
modulus := getModulus()
modulus(-1)
modulus(2)
modulus(-5)
}
func getModulus() func(int) int {
count := 0
return func(x int) int {
count = count + 1
fmt.Printf("modulus function called %d times\n", count)
if x < 0 {
x = x * -1
}
return x
}
}
输出:
modulus function called 1 times
modulus function called 2 times
modulus function called 3 times
高阶函数
高阶函数是那些接受函数作为参数或返回函数的函数。由于函数在 Go 语言中是一阶变量,它们可以被传递,也可以从某个函数返回并赋值给一个变量。在下面的示例中。
-
print 函数接受一个类型为 func(int, int) int 的函数作为参数。
-
getAreafunc 返回一个类型为 func(int, int) int 的函数。
package main
import "fmt"
func main() {
areaF := getAreaFunc()
print(3, 4, areaF)
}
func print(x, y int, area func(int, int) int) {
fmt.Printf("Area is: %d\n", area(x, y))
}
func getAreaFunc() func(int, int) int {
return func(x, y int) int {
return x * y
}
}
输出:
12
立即调用函数(IIF)
立即调用函数(IIF) 是那些可以同时定义和执行的函数。
package main
import "fmt"
func main() {
squareOf2 := func() int {
return 2 * 2
}()
fmt.Println(squareOf2)
}
输出:
4
IIF 函数的使用案例
- 当你不想在包内或包外暴露函数的逻辑时。例如,假设有一个函数设置某个值。你可以将所有设置逻辑封装在一个 IIF 函数中。这个函数在包内外都不可调用。
变参函数
在 Go 语言中,可以接受动态数量参数的函数称为变参函数。下面是变参函数的语法。在类型前使用三个点作为前缀。
func add(numbers ...int)
代码:
package main
import "fmt"
func main() {
fmt.Println(add(1, 2))
fmt.Println(add(1, 2, 3))
fmt.Println(add(1, 2, 3, 4))
}
func add(numbers ...int) int {
sum := 0
for _, num := range numbers {
sum += num
}
return sum
}
输出:
3
6
10
方法
方法具有接收者参数。当你将一个函数附加到一个类型时,这个函数就成为该类型的方法。接收者可以是结构体或任何其他类型。方法将访问接收者的属性,并可以调用接收者的其他方法。
函数:
func some_func_name(arguments) return_values
方法:
func (receiver receiver_type) some_func_name(arguments) return_values
函数与方法之间唯一的区别在于它们提供的功能不同。
-
函数可以作为一阶对象使用并被传递,而方法则不能。
-
方法可以在接收者上进行链式调用,而函数则不能用于相同的用途。
-
可以存在不同接收者的同名方法,但在同一个包中不能存在同名的两个不同函数。
结论
这篇文章全部关于 Go 语言中的函数。希望你喜欢这篇文章。请在评论中分享反馈或错误/改进意见。
下一个教程 – 常量
上一个教程 – 所有基本数据类型
Golang 中的函数/方法重载(替代方案/变通方法)
函数/方法重载意味着可以使用相同的函数/方法名称,并具有不同数量和类型的参数
请参见此帖子了解 Go 中函数和方法之间的区别 – golangbyexample.com/difference-between-method-function-go
例如。
func X()
func X(name string)
func X(name, address string)
func X(name string, age int)
Go 不支持方法/函数重载。请查看此常见问题以了解原因 golang.org/doc/faq#overloading
根据上述常见问题,没有它一切都更简单。
我们可以通过使用变参函数来变通 GO 中的方法/函数重载
-
变参函数 – 变参函数是接受可变数量参数的函数
-
空接口 – 这是一个没有任何方法的接口。
方法/函数重载有两种情况
1.不同数量的参数,但类型相同:
上述情况可以通过变参函数轻松处理。请注意,以下代码中的参数都是同一类型,即int。
package main
import "fmt"
func main() {
fmt.Println(add(1, 2))
fmt.Println(add(1, 2, 3))
fmt.Println(add(1, 2, 3, 4))
}
func add(numbers ...int) int {
sum := 0
for _, num := range numbers {
sum += num
}
return sum
输出:
3
6
10
2.不同数量的参数和不同类型
该情况可以使用变参函数和空接口来处理
package main
import "fmt"
func main() {
handle(1, "abc")
handle("abc", "xyz", 3)
handle(1, 2, 3, 4)
}
func handle(params ...interface{}) {
fmt.Println("Handle func called with parameters:")
for _, param := range params {
fmt.Printf("%v\n", param)
}
}
输出:
Handle func called with parameters:
1
abc
Handle func called with parameters:
abc
xyz
3
Handle func called with parameters:
1
2
3
4
我们还可以使用 switch 语句来获取确切的参数并相应使用。请参见以下示例。
package main
import "fmt"
type person struct {
name string
gender string
age int
}
func main() {
err := addPerson("Tina", "Female", 20)
if err != nil {
fmt.Println("PersonAdd Error: " + err.Error())
}
err = addPerson("John", "Male")
if err != nil {
fmt.Println("PersonAdd Error: " + err.Error())
}
err = addPerson("Wick", 2, 3)
if err != nil {
fmt.Println("PersonAdd Error: " + err.Error())
}
}
func addPerson(args ...interface{}) error {
if len(args) > 3 {
return fmt.Errorf("Wront number of arguments passed")
}
p := &person{}
//0 is name
//1 is gender
//2 is age
for i, arg := range args {
switch i {
case 0: // name
name, ok := arg.(string)
if !ok {
return fmt.Errorf("Name is not passed as string")
}
p.name = name
case 1:
gender, ok := arg.(string)
if !ok {
return fmt.Errorf("Gender is not passed as string")
}
p.gender = gender
case 2:
age, ok := arg.(int)
if !ok {
return fmt.Errorf("Age is not passed as int")
}
p.age = age
default:
return fmt.Errorf("Wrong parametes passed")
}
}
fmt.Printf("Person struct is %+v\n", p)
return nil
}
注意: 无论何时未传递参数,都会替代为默认值。
输出:
Person struct is &{name:Tina gender:Female age:20}
Person struct is &{name:John gender:Male age:0}
PersonAdd Error: Gender is not passed as string
在 Go(Golang)中生成给定范围内的数字
目录
-
概述**
-
代码
概述
‘mat/rand’ 包含一个 Intn 函数,可以用来生成一个在[0,n)之间的随机数。末尾的括号表示 n 是排除的。
要了解更多关于伪随机数的含义,请查看这篇文章 – golangbyexample.com/generate-random-number-golang
下面是此方法的签名。它接受一个数字 n 并返回一个范围在 0<=x<n 的数字。
func Intn(n int) int
上述函数也可以用来生成范围在 a 到 b 之间的随机数。请看下面的程序。它用于生成一个在范围 a 到 b 之间的数字。我们还提供了一个种子值给rand,以便每次生成不同的输出。
代码
package main
import (
"fmt"
"math/rand"
"time"
)
func main() {
rand.Seed(time.Now().Unix())
//Generate a random number x where x is in range 5<=x<=20
rangeLower := 5
rangeUpper := 20
randomNum := rangeLower + rand.Intn(rangeUpper-rangeLower+1)
fmt.Println(randomNum)
//Generate a random number x where x is in range 100<=x<=200
rangeLower = 100
rangeUpper = 200
randomNum = rangeLower + rand.Intn(rangeUpper-rangeLower+1)
fmt.Println(randomNum)
}
输出:
Number between 5<=x<=20
Number between 100<=x<=200
在 Go (Golang) 中生成 n 个整数的随机数组/切片
目录
-
概述
-
代码:
概述
GO 的 math/rand 包提供了一个 Perm 方法,可以用来生成 n 个整数的伪随机切片。数组将是范围 [0,n) 内整数的伪随机排列。
要了解更多关于伪随机数的含义,请查看这篇文章 – golangbyexample.com/generate-random-number-golang
以下是该函数的签名。它接受一个数字 n 作为输入并返回排列后的切片。
func Perm(n int) []int
代码:
package main
import (
"fmt"
"math/rand"
"time"
)
func main() {
//Provide seed
rand.Seed(time.Now().Unix())
//Generate a random array of length n
fmt.Println(rand.Perm(10))
fmt.Println(rand.Perm(10))
}
输出:
[6 0 1 5 9 4 2 3 7 8]
[9 8 5 0 3 4 6 7 2 1]
在 Go (Golang) 中生成一个随机字符
目录
-
概述
-
代码
概述
golang 的 ‘mat/rand’ 包包含一个 Intn 函数,可以用来生成一个在 [0,n) 之间的随机数。末尾的括号意味着 n 是不包含的。
要了解更多关于伪随机数的含义,请查看这篇文章 – golangbyexample.com/generate-random-number-golang
以下是此方法的签名。它接收一个数字 n,并将返回一个范围在 0 <= x < n 的数字。
func Intn(n int) int
上面的函数也可以用来生成一个随机字符。请参见下面的程序,它用于生成一个字符。我们还为 rand 提供了一个种子值,以便它生成不同的输出。它用于生成:
-
随机字符在小写字母 a 到 z 之间
-
随机字符在大写字母 A 和 Z 之间
-
随机字符在大写字母 A 和 Z 之间以及小写字母 a 到 z 之间
代码
package main
import (
"fmt"
"math/rand"
"time"
)
func main() {
rand.Seed(time.Now().Unix())
//Generate a random character between lowercase a to z
randomChar := 'a' + rune(rand.Intn(26))
fmt.Println(string(randomChar))
//Generate a random character between uppercase A and Z
randomChar = 'A' + rune(rand.Intn(26))
fmt.Println(string(randomChar))
//Generate a random character between uppercase A and Z and lowercase a to z
randomInt := rand.Intn(2)
if randomInt == 1 {
randomChar = 'A' + rune(rand.Intn(26))
} else {
randomChar = 'a' + rune(rand.Intn(26))
}
fmt.Println(string(randomChar))
}
输出:
Will be lowercase between a to z
Will be uppercase between A to Z
Will be lowercase between a to z or uppsercase between A to Z
在 Go (Golang)中生成随机密码
目录
-
概述
-
代码
概述
‘math/rand’ 包含一个 Intn 函数,可用于生成[0,n)之间的伪随机数。末尾的括号表示 n 是不包含的。这个函数可以用来从字符集生成随机密码。
要了解伪随机数的含义,请查看这篇文章 – golangbyexample.com/generate-random-number-golang
以下是该方法的签名。它接受一个数字 n 作为输入,并返回一个范围为 0<=x<n 的数字。
func Intn(n int) int
在下面的代码中,我们首先定义了生成密码的字符集
lowerCharSet = "abcdedfghijklmnopqrst"
upperCharSet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
specialCharSet = "!@#$%&*"
numberSet = "0123456789"
allCharSet = lowerCharSet + upperCharSet + specialCharSet + numberSet
以下代码也处理密码必须包含特定数量的特殊字符、数字或大写字母的情况。
还请注意,一旦生成符合要求的密码,我们会在最后对其进行洗牌。为了洗牌,我们首先将其转换为一个 rune 数组。请参阅这篇文章以了解为什么需要洗牌字符串 – golangbyexample.com/shuffle-string-golang/
代码
package main
import (
"fmt"
"math/rand"
"strings"
"time"
)
var (
lowerCharSet = "abcdedfghijklmnopqrst"
upperCharSet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
specialCharSet = "!@#$%&*"
numberSet = "0123456789"
allCharSet = lowerCharSet + upperCharSet + specialCharSet + numberSet
)
func main() {
rand.Seed(time.Now().Unix())
minSpecialChar := 1
minNum := 1
minUpperCase := 1
passwordLength := 8
password := generatePassword(passwordLength, minSpecialChar, minNum, minUpperCase)
fmt.Println(password)
minSpecialChar = 2
minNum = 2
minUpperCase = 2
passwordLength = 20
password = generatePassword(passwordLength, minSpecialChar, minNum, minUpperCase)
fmt.Println(password)
}
func generatePassword(passwordLength, minSpecialChar, minNum, minUpperCase int) string {
var password strings.Builder
//Set special character
for i := 0; i < minSpecialChar; i++ {
random := rand.Intn(len(specialCharSet))
password.WriteString(string(specialCharSet[random]))
}
//Set numeric
for i := 0; i < minNum; i++ {
random := rand.Intn(len(numberSet))
password.WriteString(string(numberSet[random]))
}
//Set uppercase
for i := 0; i < minUpperCase; i++ {
random := rand.Intn(len(upperCharSet))
password.WriteString(string(upperCharSet[random]))
}
remainingLength := passwordLength - minSpecialChar - minNum - minUpperCase
for i := 0; i < remainingLength; i++ {
random := rand.Intn(len(allCharSet))
password.WriteString(string(allCharSet[random]))
}
inRune := []rune(password.String())
rand.Shuffle(len(inRune), func(i, j int) {
inRune[i], inRune[j] = inRune[j], inRune[i]
})
return string(inRune)
}
输出
输出在你的机器上会有所不同
e$e&tD19
4T$&Qmg2rA4DXD5a2OGs
在 Go(Golang)中生成随机字符串
目录
-
概述
-
代码
概述
‘mat/rand’包的 golang 包含一个Intn函数,可用于生成一个介于[0,n)之间的伪随机数。末尾的括号表示 n 是排除的。该函数可以用来从字符集生成一个随机字符串。
要了解更多关于伪随机数的含义,请查看这篇文章 – golangbyexample.com/generate-random-number-golang
下面是该方法的签名。它输入一个数字 n,并返回一个范围在 0<=x<n 内的数字 x。
func Intn(n int) int
上述函数可用于生成随机字符串。基本上,我们首先选择一个 charSet。然后我们使用上述函数生成一个随机数,再用这个随机数从 charSet 中获取一个随机字符。这个随机字符被添加到字符串中,直到我们得到一个所需长度的随机字符串。
代码
package main
import (
"fmt"
"math/rand"
"strings"
"time"
)
func main() {
rand.Seed(time.Now().Unix())
//Only lowercase
charSet := "abcdedfghijklmnopqrst"
var output strings.Builder
length := 10
for i := 0; i < length; i++ {
random := rand.Intn(len(charSet))
randomChar := charSet[random]
output.WriteString(string(randomChar))
}
fmt.Println(output.String())
output.Reset()
//Lowercase and Uppercase Both
charSet = "abcdedfghijklmnopqrstABCDEFGHIJKLMNOP"
length = 20
for i := 0; i < length; i++ {
random := rand.Intn(len(charSet))
randomChar := charSet[random]
output.WriteString(string(randomChar))
}
fmt.Println(output.String())
}
输出:
下面是我机器上的输出。在你的机器上可能会给出不同的输出。
himsemkpkd
nHaiEpccEdBfCFPtaBbi
在上面的程序中,我们使用的字符集为
abcdedfghijklmnopqrst and abcdedfghijklmnopqrstABCDEFGHIJKLMNOP
在上述字符集中,所有字符都是 ASCII 字符,因此我们能够在charSet字符串中索引一个字符。但如果charSet包含非 ASCII 字符,这可能会成为一个问题。
在 Golang 中,字符串是字节的序列。字符串字面量实际上表示 UTF-8 字节序列。在 UTF-8 中,ASCII 字符是单字节的,对应前 128 个 Unicode 字符。所有其他字符占用 1 到 4 个字节。因此,不可能在字符串中索引一个字符。在 GO 中,rune 数据类型表示一个 Unicode 点。一旦字符串被转换为一个 rune 数组,就可以在该数组中索引字符。
因此,如果字符集包含一些非 ASCII 字符,它们可能会占用多个字节。在这种情况下,我们不能使用上述代码生成随机字符串,因为无法在 charSet 中索引。对此,我们必须首先将字符串转换为 rune 数组,以便能够在 rune 数组中索引字符,然后逐步形成随机字符串。
在下面的示例中,我们的 charSet 包含一个非 ASCII 字符'£'。该字符占用两个字节。
package main
import (
"fmt"
"math/rand"
"strings"
"time"
)
func main() {
rand.Seed(time.Now().Unix())
//Only lowercase and £
charSet := []rune("abcdedfghijklmnopqrst£")
var output strings.Builder
length := 10
for i := 0; i < length; i++ {
random := rand.Intn(len(charSet))
randomChar := charSet[random]
output.WriteRune(randomChar)
}
fmt.Println(output.String())
output.Reset()
//Lowercase and Uppercase Both and £
charSet = []rune("abcdedfghijklmnopqrstABCDEFGHIJKLMNOP£")
length = 20
for i := 0; i < length; i++ {
random := rand.Intn(len(charSet))
randomChar := charSet[random]
output.WriteRune(randomChar)
}
fmt.Println(output.String())
}
输出:
下面是我机器上的输出。在你的机器上可能会给出不同的输出。
aidqpbse£j
rebhjblsePsLpGBPOhfB
在 Go (Golang) 中生成一个 UUID/GUID
UUID 也称为 GUID,是一个 16 字节或 128 位的数字。它旨在唯一标识某个事物。UUID 的一些属性包括
-
UUID 很可能与生成的其他 UUID 不同。实际上,如果你生成 10 万亿个 UUID,两个 UUID 相同的概率为 .00000006。
-
UUID 的生成不依赖于任何中央服务器。
-
UUID 表示为 32 个十六进制数字(基数 16),以 5 个部分用连字符分隔。格式为 8-4-4-4-12。因此总共有 36 个字符,其中包括 32 个十六进制数字和 4 个连字符。以下是一个示例
705e4dcb-3ecd-24f3-3a35-3e926e4bded5
有不同的库可用于生成 UUID。让我们看看两个可以用来生成 UUID 的库
代码:
package main
import (
"fmt"
"strings"
"github.com/google/uuid"
)
func main() {
uuidWithHyphen := uuid.New()
fmt.Println(uuidWithHyphen)
uuid := strings.Replace(uuidWithHyphen.String(), "-", "", -1)
fmt.Println(uuid)
}
输出:
cda6498a-235d-4f7e-ae19-661d41bc154c
cda6498a235d4f7eae19661d41bc154c
代码
package main
import (
"fmt"
"strings"
"github.com/pborman/uuid"
)
func main() {
uuidWithHyphen := uuid.NewRandom()
fmt.Println(uuidWithHyphen)
uuid := strings.Replace(uuidWithHyphen.String(), "-", "", -1)
fmt.Println(uuid)
}
输出:
cda6498a-235d-4f7e-ae19-661d41bc154c
cda6498a235d4f7eae19661d41bc154c
在 Go (Golang)中生成随机数
目录
-
概述
-
什么是伪随机数
-
rand 包中的随机生成器函数
-
具有范围的伪随机数生成器函数。
-
没有范围的伪随机数生成器函数。
-
伪随机数生成器函数(适用于浮点数的范围)
-
-
代码
概述
Go 提供了一个‘math/rand’包,内置支持生成伪随机数。此包定义了可以用于生成的各种方法。
-
从 0 到 n 的伪随机数
-
未指定范围的伪随机数。范围将取决于 int 的类型,即 int64、int32、uint64 等。
什么是伪随机数
在继续之前,先理解一下伪随机数的含义。伪随机数并不是真正随机的,因为其值完全由初始值(称为种子)决定。
要理解种子的作用,我们首先看一下可以生成范围为[0, n)的随机数的基本函数。下面的函数在rand包中可以用于生成范围为[0, n)的伪随机数。末尾的括号[0,n)表示 n 是排除的。
func Intn(n int) int
上述函数返回一个在 0 到 n 之间的 int 值。让我们写一个没有种子值的程序。我们传递了 10,因此下面的函数将在范围[0,10)内生成随机数。
package main
import (
"fmt"
"math/rand"
)
func main() {
fmt.Println(rand.Intn(10))
fmt.Println(rand.Intn(10))
fmt.Println(rand.Intn(10))
}
尝试多次运行上述程序。每次都会得到相同的输出。在我的系统上,输出如下。
7
7
7
现在让我们尝试运行相同的程序,但首先提供种子值。
package main
import (
"fmt"
"math/rand"
"time"
)
func main() {
rand.Seed(time.Now().Unix())
fmt.Println(rand.Intn(10))
fmt.Println(rand.Intn(10))
fmt.Println(rand.Intn(10))
我们将种子值设为自 1970 年 1 月 1 日 UTC 以来经过的秒数。
rand.Seed(time.Now().Unix())
每次执行此程序时都会给出不同的输出,因为种子值不同。这就是我们所说的 Go 生成伪随机数的含义。
rand 包中的随机生成器函数
现在我们已经理解了伪随机数生成,让我们看看 rand 包中提供的一些用于生成随机数的函数。你可以根据需求使用这些函数中的任何一个来生成随机数。
具有范围的伪随机数生成器函数。
所有函数将 n 作为参数,如果 n<=0,则会出现恐慌。
-
Intn(n int) – 返回一个非负的伪随机数,范围在[0,n)内
-
Int31n(n int32) – 返回一个非负的伪随机数,范围在[0,n)内,返回类型为 int32
-
Int63n(n int64) – 返回一个非负的伪随机数,范围在[0,n)内,返回类型为 int64
无范围的伪随机数生成器函数。
-
Int() – 返回一个非负的伪随机整数
-
Int31() – 返回一个非负的伪随机 31 位整数,类型为 int32
-
Int63() – 返回一个非负的伪随机 63 位整数,类型为 int64
-
Uint32() – 返回一个伪随机的 32 位值,类型为 uint32
-
Uint64() – 返回一个伪随机的 64 位值,类型为 uint64
有范围的伪随机数生成器函数(用于浮点数)
-
Float64() – 返回一个伪随机数,范围在[0.0,1.0)内,类型为 float64
-
Float32() – 返回一个伪随机数,范围在[0.0,1.0)内,类型为 float32
代码
package main
import (
"fmt"
"math/rand"
"time"
)
func main() {
rand.Seed(time.Now().Unix())
//Pseudo Random Number Generator Functions with range
//1\. Intn(n int)
fmt.Printf("Intn: %d\n", rand.Intn(10))
//2\. Int31n(n int32)
fmt.Printf("Int31n: %d\n", rand.Int31n(10))
//3\. Int64n(n int32)
fmt.Printf("Int64n: %d\n", rand.Int63n(10))
//Pseudo Random Number Generator Functions without range.
//1\. Int()
fmt.Printf("Int: %d\n", rand.Int())
//2\. Int31()
fmt.Printf("Int31: %d\n", rand.Int31())
//3\. Int63()
fmt.Printf("Int63: %d\n", rand.Int63())
//4\. Uint32()
fmt.Printf("Uint32: %d\n", rand.Uint32())
//4\. Uint64()
fmt.Printf("Uint64: %d\n", rand.Uint64())
//Pseudo Random Number Generator Functions with range for floats
//1\. Float64()
fmt.Printf("Float64: %f\n", rand.Float64())
//2\. Float32()
fmt.Printf("Float32: %f\n", rand.Float32())
}
输出:
Intn: 9
Int31n: 4
Int64n: 4
Int: 6567086139449890598
Int31: 402632083
Int63: 428924242891364663
Uint32: 1991553101
Uint64: 825780166485441015
Float64: 0.683701
Float32: 0.382141
在 Go 语言中生成有效括号
目录
- 概述
概述
给定一个整数 n,表示括号对的数量,生成所有有效的成对括号。
例如
Input:1
Output: [()]
Input:2
Output: [()(), (())]
Input:2
Output: [()()() ()(()) (())() (()()) ((()))]
程序的想法是使用两个整数
-
open – 它表示到目前为止使用的左括号的数量
-
close – 它表示到目前为止使用的右括号的数量
我们仅在
open < n //where n is the number of pairs of parentheses
我们仅在
close < open //Number of right parentheses is less than the number of left parentheses
以下是相应的程序
package main
import "fmt"
func main() {
output := generateParenthesis(1)
fmt.Println(output)
output = generateParenthesis(2)
fmt.Println(output)
output = generateParenthesis(3)
fmt.Println(output)
}
func generateParenthesis(n int) []string {
input := ""
for i := 0; i < n; i++ {
input = input + " "
}
output := generateParenthesisUtil(0, n, 0, 0, []rune(input))
return output
}
func generateParenthesisUtil(pos, n, open, close int, input []rune) []string {
var output []string
if pos == n*2 {
output = append(output, string(input))
return output
}
if close < open {
input[pos] = ')'
result := generateParenthesisUtil(pos+1, n, open, close+1, input)
output = append(output, result...)
}
if open < n {
input[pos] = '('
result := generateParenthesisUtil(pos+1, n, open+1, close, input)
output = append(output, result...)
}
return output
}
输出
[()]
[()() (())]
[()()() ()(()) (())() (()()) ((()))]
注意: 查看我们的 Golang 高级教程。本系列教程内容详尽,我们尽力涵盖所有概念及示例。本教程适合那些希望掌握 Golang 并深入理解的读者 - Golang 高级教程
如果你对理解如何在 Golang 中实现所有设计模式感兴趣。如果是的话,这篇文章适合你 - 所有设计模式 Golang
在 Go (Golang) 中获取数字的绝对值
目录
-
概述
-
代码:
概述
GO 的 math 包提供了一个 Abs 方法,可以用来获取数字的绝对值。
以下是该函数的签名。它接受一个浮点数作为输入,并返回一个浮点数。
func Abs(x float64) float64
Abs 函数的一些特殊情况是
-
Abs(±0) = ±0
-
Abs(±Inf) = ±Inf
-
Abs(NaN) = NaN
代码:
package main
import (
"fmt"
"math"
)
func main() {
res := math.Abs(-2)
fmt.Println(res)
res = math.Abs(2)
fmt.Println(res)
res = math.Abs(3.5)
fmt.Println(res)
res = math.Abs(-3.5)
fmt.Println(res)
}
输出:
2
2
3.5
3.5
在 Go(Golang)中根据 DOB 获取年龄
本教程将讨论如何根据出生日期计算一个人的年龄。go-age 帮助我们完成这个任务。在计算年龄时,它还考虑了闰年的复杂性。
请看下面的工作示例:
package main
import (
"fmt"
"time"
age "github.com/bearbin/go-age"
)
func main() {
dob := getDOB(2011, 4, 2)
fmt.Printf("Age is %d\n", age.Age(dob))
}
func getDOB(year, month, day int) time.Time {
dob := time.Date(year, time.Month(month), day, 0, 0, 0, 0, time.UTC)
return dob
}
输出:
Age is 8
从 GO(Golang)中的句子获取所有单词
目录
-
概述
-
代码:
概述
在 GO 中,字符串是 UTF-8 编码的。GO 的 strings 包提供了一个 Fields 方法,可以用于根据一个或多个连续空白字符的实例来分割字符串。
以下是函数的签名
func Fields(s string) []string
正如你所注意到的,它返回了输入字符串的子字符串切片。此外,请注意,如果输入字符串为空,它将返回一个空切片。
-
输入字符串为空
-
输入字符串仅包含空白字符
代码:
package main
import (
"fmt"
"strings"
)
func main() {
//Case 1 Input string contains single spaces
res := strings.Fields("ab cd ef")
fmt.Println(res)
//Case 2 Input string doesn't contain white spaces
res = strings.Fields("abcdef")
fmt.Println(res)
//Case 3 Input string contains double white spaces and spaces at end too.
res = strings.Fields("ab cd ef ")
fmt.Println(res)
//Case 4: Input string contain white spaces only. Will output a empty slice
res = strings.Fields(" ")
fmt.Println(res)
//Case 5: Input string is empty. Will output a empty slice
res = strings.Fields("")
fmt.Println(res)
}
输出:
[ab cd ef]
[abcdef]
[ab cd ef]
[]
[]
```*
<!--yml
类别:未分类
日期:2024-10-13 06:17:42
-->
# 在 Go (Golang)中获取任意字母或数字的 ASCII 代码/值
> 来源:[`golangbyexample.com/get-ascii-value-alphabet-go/`](https://golangbyexample.com/get-ascii-value-alphabet-go/)
**遍历**字符串可以获取字符串中所有字符的**ASCII**值。在下面的代码中,我们打印小写字母、大写字母和数字的 ASCII 值。
```go
package main
import "fmt"
func main() {
lowercase := "abcdefghijklmnopqrstunwxyz"
for _, c := range lowercase {
fmt.Println(c)
}
uppercase := "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
for _, c := range uppercase {
fmt.Println(c)
}
numbers := "0123456789"
for _, n := range numbers {
fmt.Println(n)
}
}
输出:
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
110
119
120
121
122
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
48
49
50
51
52
53
54
55
56
57