Golang基础-7

【7】深入探索 Golang 指针:从基础到实战的全面指南 Golang 指针的全面介绍,包括基础概念、使用方法、与函数和结构体的结合、使用场景、注意事项以及空指针问题的处理,相信你对 Golang 指针有了更深入的理解和掌握。在实际开发中,合理使用指针可以提高程序的性能和灵活性,但也要注意避免因指针使用不当带来的问题。 阅读详情

Go语言基础

介绍

基础

介绍

  • 本文介绍Go语言中函数(函数定义、函数调用、函数形参、函数返回值、递归函数、匿名函数与闭包)等相关知识。

基础

函数
  • 函数是对代码片段的逻辑封装的集合。函数的作用就是提供代码复用性。
  • 函数之间属于并列关系,main 函数是程序执行的入口,且程序中只能有一个 main 函数。
  • 函数名称必须遵守Go语言命名规范,首字母大写表示对其它包可见,首字母小写表示只对本包可见。
  • 函数不支持函数重载,所以同一个包中的函数名必须不相同。
函数定义
  • 函数包含函数名、形参列表、函数体和返回值列表,使用关键字 func 声明,基本语法如下:

func 函数名称 (形参列表) (返回值列表) {
函数体
return + 返回值列表
}

package main

import "fmt"

// 无形参、无返回值
func main() {
	print(10, 20)
	fmt.Printf("a + b = %v\n", sum(10, 20))
}

// 有形参、无返回值
func print(a, b int) {
	fmt.Printf("a = %v, b = %v\n", a, b)
}

// 有形参、有返回值
func sum(a, b int) int {
	return a + b
}
函数调用
  • 函数之间属于并列关系,不允许在一个函数中定义另一个函数,可以在一个函数中调用另一个函数。
package main

import "fmt"

func main() { // main 函数中调用其它函数
	empty()                                 // 调用无参、无返回值函数
	print(10, 20)                           // 调用有参、无返回值函数
	fmt.Printf("a + b = %v\n", sum(10, 20)) // 调用有参、有返回值函数
	sum(20, 30)                             // 忽略函数返回值
}

func empty() { // 无形参、无返回值
	fmt.Println("empty")
}

func print(a, b int) { // 有形参、无返回值
	fmt.Printf("a = %v, b = %v\n", a, b)
}

func sum(a, b int) int { // 有形参、有返回值
	return a + b
}

输出结果
empty
a = 10, b = 20
a + b = 30

函数形参
  • 形参列表可以是 0 到 多个形参。函数形参支持可变参数,将可变参当作切片处理。可变参数只能定义一个,且只能在形参列表末端
package main

import "fmt"

func main() {
	test(10, 20, 30, 40, 50)

	// 将切片解包传递给函数形参
	test([]int{30, 40, 50}...)

	s := []int{30, 40, 50}
	test(s...)
	test(s[:1]...)
}

func test(args ...int) { // 可变参函数,将可变参数初始化为切片处理
	for i, v := range args {
		fmt.Printf("args[%v] = %v\t", i, v)
	}
	fmt.Println()
}

输出结果
args[0] = 10 args[1] = 20 args[2] = 30 args[3] = 40 args[4] = 50
args[0] = 30 args[1] = 40 args[2] = 50
args[0] = 30 args[1] = 40 args[2] = 50
args[0] = 30

  • 基本数据类型和数组是值传递,将实际参数拷贝一份到函数内部使用。若不想值传递,函数形参使用指针类型。
package main

import "fmt"

func main() {
	var a int = 10
	var b int = 20
	fmt.Printf("swap before: a = %v, b = %v\n", a, b)
	swap(a, b)
	fmt.Printf("swap after: a = %v, b = %v\n", a, b)
	fmt.Println("====================================")
	fmt.Printf("swap before: a = %v, b = %v\n", a, b)
	swap2(&a, &b)
	fmt.Printf("swap after: a = %v, b = %v\n", a, b)
}

func swap(a int, b int) { // 基本数据类型,将实参拷贝一份
	a, b = b, a
	fmt.Printf("swap: a = %v, b = %v\n", a, b)
}

func swap2(a *int, b *int) { // 通过指针实现两值交换,指针指向实参内存位置
	*a, *b = *b, *a
	fmt.Printf("swap ptr: a = %v, b = %v\n", *a, *b)
}

输出结果
swap before: a = 10, b = 20
swap: a = 20, b = 10
swap after: a = 10, b = 20
====================================
swap before: a = 10, b = 20
swap ptr: a = 20, b = 10
swap after: a = 20, b = 10

  • 形参列表中,对连续相同的类型可以对类型进行合并。
package main

import "fmt"

func main() {
	test(1, 2)
	test2(1, 2)
}

func test(a int, b int) { // 未合并形参类型
	fmt.Printf("test: a = %v, b = %v\n", a, b)
}

func test2(a, b int) { // 连续相同的形参变量类型进行合并
	fmt.Printf("test2: a = %v, b = %v\n", a, b)
}

输出结果
test: a = 1, b = 2
test2: a = 1, b = 2

函数返回值
  • 返回值类型列表数量可以存在 0 到多个返回值。
package main

import "fmt"

func main() {
	test()
	fmt.Println("test1: ", test1())

	a, b, c := test2()
	fmt.Printf("test2: %v, %v, %v\n", a, b, c)
}

func test() { // 无返回值
	fmt.Println("no return")
}

func test1() int { // 有一个返回值
	return 10
}

func test2() (int, int, int) { // 有多个返回值
	return 10, 20, 30
}

输出结果
no return
test1: 10
test2: 10, 20, 30

  • 函数返回值可以命名,函数内部通过此变量名给返回值赋值。
package main

import "fmt"

func main() {
	fmt.Println("test1: ", test1())

	a, b, c := test2()
	fmt.Printf("test2: %v, %v, %v\n", a, b, c)

	d, e, f := test3()
	fmt.Printf("test3: %v, %v, %v\n", d, e, f)
}

func test1() (r int) { // 有一个返回值
	r = 10
	return
}

func test2() (r1, r2, r3 int) { // 有多个返回值
	r1 = 10
	r2 = 20
	r3 = 30
	return
}

func test3() (r1 int, r2 int, r3 int) { // 有多个返回值
	r1 = 10
	r2 = 20
	r3 = 30
	return
}

输出结果
test1: 10
test2: 10, 20, 30
test3: 10, 20, 30

  • 函数也可以作为一种数据类型,可存储在容器中,也可作为函数参数传入或作为函数返回值。
package main

import "fmt"

func main() {
	// 函数类型变量
	var f func() int = test1
	fmt.Printf("a type: %T\n", f)
	f()

	// 函数类型作为形参
	fmt.Println("test2: ", test2(test1))

	// 函数类型作为返回值
	fmt.Println("test3: ", test3()())
}

func test1() (r int) { // 有一个返回值
	r = 10
	return
}

func test2(f func() int) (r int) { // 有一个返回值
	r = f()
	return
}

func test3() (f func() int) { // 有一个返回值
	f = test1
	return
}

输出结果
a type: func() int
test2: 10
test3: 10

递归函数
  • 递归函数是指在函数内部继续调用自己的函数。
  • 编写递归函数时必须要有终止条件,否则会无限次调用,内存溢出。
package main

import "fmt"

func main() {
	// 打印斐波那契数列
	for i := 1; i < 10; i++ {
		fmt.Print(fibonacci(i), ", ")
	}
	fmt.Println()

	// 打印阶乘
	for i := 1; i < 10; i++ {
		fmt.Print(factorial(uint32(i)), ", ")
	}
	fmt.Println()

}

// 计算斐波那契数列,n < 3时值为1,n > 2时,数值为前两个位置数值之和
func fibonacci(n int) (ret int) {
	if n < 3 {
		ret = 1
		return
	}

	ret = fibonacci(n-1) + fibonacci(n-2)
	return
}

// 计算正整数的阶乘(所有小于等于该数的正整数的积),0 的阶乘为 1
// n!=1×2×3×…×n
func factorial(n uint32) (ret uint32) {
	if n < 2 {
		ret = 1
		return
	}

	ret = n * factorial(n-1)
	return
}

输出结果
1, 1, 2, 3, 5, 8, 13, 21, 34,
1, 2, 6, 24, 120, 720, 5040, 40320, 362880,

匿名函数与闭包
  • 未指定函数名称的函数称之为匿名函数
  • 可以在局部代码块中使用、也可以作为其它函数的形参类型
package main

import "fmt"

func main() {
	// 定义匿名函数赋值给一个变量,通过变量调用匿名函数
	print := func() {
		fmt.Println("function 1")
	}

	print()

	// 定义匿名函数并调用
	func() {
		fmt.Println("function 2")
	}()

	// 调用形参传递匿名函数
	test(func() {
		fmt.Println("function 3")
	})
}

// 匿名函数作为函数形参
func test(print func()) {
	print()
}

输出结果
function 1
function 2
function 3

  • 匿名函数又可以称为闭包,在函数内部可以定义匿名函数,此匿名函数可以引用外部函数的变量。
  • 只要使用外部函数变量,其匿名函数生命周期一直存在,不会被自动销毁。
package main

import "fmt"

func main() {
	test()
}

// 定义闭包函数,以引用方式访问外部变量
func test() {
	var a int = 10
	func() {
		fmt.Printf("func() a = %v\n", a)
		a = 20
	}()
	fmt.Printf("test() a = %v\n", a)

	fmt.Println("test2(): ", test2("Hello")(" World!"))
}

// 函数内部定义闭包函数作为返回值
func test2(a string) func(string) string { // 返回值为匿名函数
	return func(b string) string {
		return a + b
	}
}

输出结果
func() a = 10
test() a = 20
test2(): Hello World!

起始

2024年Go最新SnakeYAML配置文件解析器_snakeyaml 读取配置文件注释(7),Golang面试基础技能罗列 面经、学习笔记、源码讲义、实战项目、大纲路线、讲解视频,并且后续会持续更新**创建一个test.yaml文件在resources目录下,创建自己的实例对象类MyInstance。 阅读详情

相关推荐

基于bootstrap+Java的图书管理系统(任务书)

10] 倪甜弟,周晓波,王相喜.基于JSP图书馆自习室预约系统的设计与实现[J].现代计算机, 2024, 30(9):117-120.DOI:10.3969/j.issn.1007-1423.2024.09.023.[2] 陈明雪,赵勇,周小丽,等.基于Node.js和Bootstrap的图书管理系统设计与研究[J].现代信息科技, 2021, 5(24):4.[9] 杨婷婷.基于VOSviewer的图书馆管理系统研究的可视化分析[J].现代信息科技, 2023, 7(3):123-126.

毕业作品网站 647

Go语言零基础入门指南:7天掌握Golang核心技术与实战技巧

快速掌握Go语言核心技能,零基础也能轻松入门。本指南提供系统化的go语言学习资料,涵盖语法基础、并发编程、Web开发等实战内容,7天高效进阶。适合后端开发与云服务场景,方法实用、案例丰富,值得收藏。

ProceNest的博客 1100

抖音__NS_sig3签名机制解析与动态Hook实战

在现代移动应用中,客户端与服务端之间的可信通信契约往往依赖于动态生成的请求签名,如抖音(某手)的__NS_sig3参数。该签名并非简单哈希,而是融合设备指纹、传感器数据、运行时上下文与轻量加密的综合摘要,体现了‘环境即凭证’的安全设计思想。其核心价值在于抵御静态伪造与批量模拟,提升接口调用的真实性与不可复用性。典型应用场景包括Feed流加载、点赞关注等关键业务接口的身份校验。本文基于真实逆向与Frida动态Hook实践,深入解析__NS_sig3的so层实现逻辑、JNI调用链路、输入参数真实性验证机制,以及

weixin_30127995的博客 375

如何在7天内通过A Tour of Go快速掌握Go语言编程基础

想学习Go语言却不知从何开始?面对复杂的编程概念感到困惑?别担心,A Tour of Go为你提供了一个完美的解决方案!这个交互式学习平台让Go语言学习变得简单有趣,即使你是编程新手,也能在短时间内掌握核心概念。通过A Tour of Go,你可以在浏览器中直接编写和运行Go代码,无需复杂的开发环境配置,真正实现零门槛入门。 ## 为什么选择A Tour of Go作为你的Go语言学习起点?

gitblog_01206的博客 913

你不知道的Postman的Mock接口测试,看这一篇就够了

创建Mock服务你可以从Postman已有的测试集(Collection)中创建Mock Server或者直接创建Mock Server(我们这里选择从已有的测试集中创建Mock Server)Mock server详细配置页面,在此页面中我们可以设置:命名Mock Server选择一个环境(可选的),我们可以选择之前设置过的环境,Mock Server将会使用对应环境中设置过的变量在对应的请求和响应中如果想要将Mock Server设置私有访问的,那么可以勾选此选项,不勾选则对所有人可见。

654

图形引擎实战:镭射效果制作分享

该方案的优势1.遵循物理的2.可以使用少量的参数去调控镭射的效果。计算相对简单,缺点仍是颜色不能够自定义,还有一种常见的方案是采样一张镭射贴图来模拟,好处是颜色可以自定义同时性能上还很高效没有复杂的公式计算。我查阅了网上普遍的方案,常见的做法是制作一个Ramp图生成工具,然后将生成好的ramp图赋给材质。这两个方案的好处是美术同学可以手动的去控制镭射的颜色。最后就是Shader中对Ramp图的采样的部分,Ramp图的UV坐标是使用fresnel作为Ramp的U轴坐标,0.5作为V轴坐标。

qq_41166022的博客 1353

【Go语言0基础学习之旅#7】 Golang标识符基本知识

🎉本篇文章主要讲解Golang中标识符的基本知识点、使用注意事项、保留关键字和预定标识符。

m0_56262476的博客 417

从零构建AI Agent集群:Docker Compose与Nginx部署实战

在AI应用开发领域,微服务架构和容器化部署已成为提升开发效率和系统可维护性的关键技术。Docker Compose作为容器编排工具,能够将多个独立服务(如Node.js、Python应用)及其依赖(数据库、缓存)封装在隔离环境中,并通过统一配置文件定义服务间的网络与依赖关系,实现一键启停。Nginx作为反向代理,则提供了统一的网络入口、请求路由和负载均衡能力,是构建高可用Web应用的基石。这种组合技术方案的价值在于,它能将复杂的AI系统(如工作流引擎、对话Agent、技能库)的部署运维复杂度大幅降低,使得开

weixin_27028523的博客 638

Golang基础7-并发编程

Golang基础-并发编程

m0_61973596的博客 1550

Android息屏后台任务保活实战:从定时器失效到厂商白名单破解

本文深入探讨了Android应用在息屏后定时任务失效的根源,即系统为省电而触发的休眠机制。文章提供了从传统方案失效分析到实战破解的完整路径,核心在于引导用户将应用加入电池优化白名单并开启自启动权限,从而合法绕过限制。同时,结合WorkManager、AlarmManager等可靠定时方案,实现稳定的后台任务执行。

weixin_28475533的博客 423

基于网关实现不同网段S7-1200 CPU的通信方法

在A网段的计算机上ping B网段的计算机:在A网段的计算机上使用ping命令,向B网段的计算机发送数据包。在B网段的计算机上ping A网段的计算机:同样地,在B网段的计算机上使用ping命令,向A网段的计算机发送数据包。数据包也会经过路由器进行转发,最终到达A网段的计算机。配置路由器:在路由器上配置两个网段的IP地址和子网掩码,并设置路由表,使得路由器可以将A网段和B网段之间的数据进行转发。确定两个网络之间的路由器:假设需要将A网段和B网段进行通信,需要在A、B两个网段之间设置一台路由器。

电工 2400

服务计算第二周 Go 开发环境安装

服务计算 第二周Go开发环境安装1.选用编辑器2.安装golang2.1安装2.2配置路径2.3Hello World小程序3.安装 Git4.了解Golang4.1构建并安装程序4.2建立一个字符反转库,为hello提供保障4.3尝试使用测试文件4.4调用远程包我的github 1.选用编辑器 本人使用的是CentOS7,为了节省空间而使用了服务器版,因此没有安装桌面。一般来说,Go语言使用...

Yanzu_Wu的博客 527

智能车图像处理20-进阶篇12--正入十字补线1

这篇文章主要讲述基本的正入十字补线方法。

taiyuezyh的博客 6941

快速搞定跨设备笔记同步:Joplin多平台实操指南

Joplin 是一款免费开源的笔记与待办应用,覆盖 Windows、macOS、Linux、Android、iOS 五个平台。它的思路很直接:数据先存在你自己设备上,再用你自选的云端做同步,笔记内容永远掌握在你手里。适合想脱离 Evernote、又希望笔记能免费在多台设备间流转的人。 [![Joplin跨设备笔记同步:同一套笔记本在平板与手机上流转](https://raw.gitcode.co

gitblog_00588的博客 319

jre9下载 jdk9

(Java SE Runtime Environment 9.0) 9.0u175 官方最新版 【x86|x64】

C# WinForm 基于DirectShow.dll编写的程序,可边预览边保存视频,音频和图片

基于微软的DirectShow.dll的二次开发1.自动识别连接的摄像头跟麦克风且可以对其进行选择(默认选中第一个)2.可录制wmv和avi两种格式的视频并且都带有音频,avi可以录制的分辨率和帧数进行选择,wmv默认进行了淸晰度优化如不喜欢可去除代码中有相关提示3.可在预览点开之后进行拍照,也可边录制视频边拍照4.添加了视频和音频的压缩功能(酌情使用)这次二次开发发现C#对DirectShow的相关信息太少,这次做完也不敢藏私共享出来,还望大家指正

Golang基础(7)

每个程序都会遇到错误。你应该为它们做好计划。有时候,处理错误可以像报告错误并退出程序一样简单。但是其他错误可能需要额外的操作。你可能需要关闭打开的文件或网络连接,或者以其他方式清理,这样你的程序就不会留下混乱。 我们知道在C++中对堆区的内存由程序员手动分配手动释放。如果在释放内存之前程序崩溃,那么很有可能内存是没有释放,这样的情况出现多了,会不断消耗内存,进而影响操作系统的性能。 可以通过defer语句去处理这个问题。你可以将defer关键字放在任何普通函数或方法调用之前,Go将延迟(也就是推迟)执行函数

肖恩123的博客 908

WINCC7.3破解文件

WINCC7.3硬件够破解文件,有需要的下载!WINCC7.3硬件够破解文件,有需要的下载!

Go最新Win7使用teredo连接IPv6的方法_teredo v6验证(3),Golang开发基础学习

查看 Teredo 参数 ,若状态为 qualified ,则 OK ,用 ipconfig /all 查看 Teredo 适配器是否获得以 2001:0 为前缀的 IPv6 地址。若状态仍未 offline ,需要再次尝试连接服务器,即输入之前的命令。因不能确保一次就能连上,可能出现需要多次连接的情况。之后需要稍等一阵 ,因为在请求连接 Teredo 服务器,此时输入。即 “ 状态 ”为 probe ,表示正在请求中。10 秒之后(或稍长些), 输入。路线、讲解视频,并且后续会持续更新**

2401_84920041的博客 255

文档:亲测可用解决vnc灰屏,黑屏,鼠标大黑叉情况

主要解决vnc-viewer灰屏,黑屏,鼠标大黑叉等现象,详细见文档。

Golang语言基础【7】触发调度

本文是学习https://draven.co/golang/docs/part3-runtime/ch07-memory/golang-memory-allocator/的笔记,请打击支持原作者

zasx1994的专栏 717

go语言基础(7)

package main import "fmt" func main01() { var a int = 123 //定义整型指针变量 指向a的地址 //指针类型定义 //var 指针 *数据类型 一级指针 var p *int //将a的地址赋值给指针变量p p=&a //通过指针变量 间接访问变量对应的内存空间 *p=345 fmt.Println(...

u011406059的博客 313

『Go基础』第7节 变量

1. 什么是变量? 我们应该怎么去理解变量? 在这里我要举一个例子: 大家应该都知道王者荣耀这个游戏. 当我们在玩王者荣耀的时候, 我们操控的英雄的血量是不断变化的, 这个血量是存在内存中的. 那么这个血量就是一个变量. 在程序运行的过程中, 其值可以改变的量, 我们就称为变量. 通过上面例子可以发现: 变量是存储在内存中的 变量是可以改变的 我们说变量是存储在内存中, 那么内存又是...

weixin_30929011的博客 695

非零基础自学Golang 第2章 安装和运行Go 2.3 在Linux 下安装Go & 2.4 在Mac OS 下安装Go

非零基础自学Golang 第2章 安装和运行Go 2.3 在Linux 下安装Go & 2.4 在Mac OS 下安装Go

代码改变世界 534

Centos7 Go的安装、配置及基础命令

一、Go简介: 1.1 特点 1.2 优势 1.3 劣势 二、Go安装与环境配置: 2.1 下载及安装 2.2 环境配置 2.3 测试 三、基本准则: 3.1 相关概念 3.2 源码文件的分类及含义 3.3 代码包相关知识 3.4 init函数执行时机 四、Go命令基础: 4.1 go run 4.2 go build 4.3 go install 4.4 go get 一、Go简介 1.1 特点 1.1.1 静态类型、编译型的开源语言: 静态类型意味着在编写go语言程序中,

jstang的博客 5170

Go语言基础系列

Golang(1)Golang语言简介 Golang(2)win10下安装Go语言 Golang(3)CentOS7系统安装Go语言

redrose2100的博客 347

非零基础自学Golang 第7章 函数 7.8 知识拓展

非零基础自学Golang 第7章 函数 7.8 知识拓展

代码改变世界 277

7Go语言基础之切片

本文是李文周的博客go语言学习之路的目录提要版,方便复习查看使用,原文参见文章连接: https://www.liwenzhou.com/posts/Go/go_menu/ 本文主要介绍Go语言中切片(slice)及它的基本使用。 切片总结 引子:数组的长度是固定的,且是值传递,数组在使用的时候有很多的局限性 切片:切片是一个引用类型,它的内部结构包含地址、长度和容量。切片一般用于快速地操作一块数...

weixin_42426385的博客 189

golang基础小记(7)——切片:初始化、基础概念

切片(slice) 切片(Slice)是一个拥有相同类型元素的可变长度的序列。切片是引用类型,本身并不存储任何数据,其内部包括地址、长度、容量,其底层是数组,所以地址指向底层数组的对应元素。另外,长度是切片的元素个数,容量是长度的最大值,超过则需要扩容。 切片长度和容量可以通过内置的len()函数和cap()函数获得。 var s = []int{1, 2, 3} fmt.Println("长度:", len(s), "容量:", cap(s)) // 长度: 3 容量: 3 初始化 直接声明 直接声明得

m0_37710023的博客 3844

Go基础 7数组与切片

7 数组与切片 7.1 声明和初始化 var identifier [len]type //e.g. var array [10]int 注意:Go语言中的数组是一种值类型,可以通过new()来创建:var arr1 = new([5]int) 这种方式和var arr2 [5]int的区别是: arr1类型是*[5]int,arr2的类型是[5]int。 在函数中数组作为参数传入时,如func1(arr2),会产生一次数组拷贝,func1方法不会修改原始的数组arr2。如果想修改原数组,那么arr2必

qq_39657702的博客 806
上一篇: Golang基础-6
下一篇: Golang基础-8
无夜_
博客等级 码龄7年 2916粉丝 51原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值