go 语言概述

【Go语言入门教程】Go语言简介 Go语言(或Golang)起源于2007年,并在2009年正式对外发布。Go是非常年轻的一门语言,它的主要目标是“兼具Python等动态语言的开发速度和C/C++等编译型语言的性能与安全性”。Go语言是编程语言设计的又一次尝试,是对类C语言的重大改进,它不但能让你访问底层操作系统,还提供了强大的网络编程和并发编程支持。Go语言的用途众多,可以进行网络编程、系统编程、并发编程、分布式编程。Java或C++看起来并不相同。但是它通过接口(interface)的概念来实现多态性。... 阅读详情

1. Go语言从何而来?

关于Go语言的萌芽时期,我们可以追溯至上个世纪。不过,直至2009年,它才真正被披露,并成为开源大家庭中的一员。在2012年,Go语言的创造者们发布了它的1.0版本。大家可能有所耳闻,Go语言出自Google公司。但很多人可能并不清楚,它的创造者们更是名头不小。他们包括Unix操作系统和B语言(C语言的前身)的创造者、UTF-8编码的发明者Ken Thompson,Unix项目的参与者、UTF-8编码的联合创始人和Limbo编程语言(Go语言的前身)的创造者Rob Pike,以及著名的Javascript引擎V8的创造者Robert Griesemer。正因为有了他们的引领,一批又一批的全球顶尖计算机软件人才都相继加入到了Go语言项目中。

Go语言是一门强类型的通用编程语言。它的基础语法与C语言很类似,但同时也对其他的一些优秀编程语言有所借鉴。它的很多设计灵感都来源于Tony Hoare执笔的那篇著名的论文《Communicating Sequential Processes》。

2. Go语言意味着什么?

Go语言意味着更自由、更高效和一站式的编程体验,程序开发效率和运行效率之间的完美融合,以及天生的并发编程支持。

2.1自由的编程方式

我们下面重点说说Go语言对各种流行的编程范式的支持,以及它对并发编程的强悍支持。

使用Go语言就意味着你可以用自己喜欢的方式编程。因为Go语言支持当今所有主流的编程范式。这包括面向对象编程、函数式编程,以及过程式编程。

面向对象编程

面向对象的设计和编程可以使我们更容易的对现实世界进行建模。这样可以编写出让人类更易懂的代码,并且还会大大增强代码的可维护性和可扩展性。Go语言支持面向对象编程。因此,我们的Go语言程序也可以具备上述优势。面向对象编程中的很多重要原则都可以很容易的在Go语言程序中体现出来,比如:“针对接口编程,而不是针对实现编程”、“对扩展开放,对修改关闭”和“多用组合,少用继承”等等。另外,虽然Go语言中并没有继承的概念,但我们依然可以用类型嵌入的方式来模仿继承并达到相同的效果。

函数式编程

函数式编程同样可以让我们更容易的跟进变化。它可以让我们的程序实体的粒度更加小巧,从而使程序更加易变。此外,函数式编程还可以让我们的程序更加健壮,因为函数本身是没有状态的。要知道,对各种状态的维护会使程序更加复杂和脆弱。Go语言对函数式编程提供支持的一个体现就是:它的函数是绝对的一等类型。这是函数式编程的一个重要特征。更具体地说,我们可以把一个函数作为传给其他函数的参数,或成为其他函数返回的结果。这是构建闭包的必要条件。同时,这也意味着,我们可以对程序的可变部分进行更加灵活的控制和管理。

过程式编程

至于过程式编程,我们自不必多说。程序员们应该再熟悉不过了。过程式编程最直接的体现了程序的本质,同时也是简单程序的最常用的编写手法。我们可以用脚本语言写出纯过程化的程序。我之前常常使用Python代码来做这类事情。因为它可以像Shell脚本那样工作,并且总是能够保持简单。我现在的选择当然是用Go语言。不论是语言语法还是程序运行方式,Go语言都非常的脚本化。简约和易用是它的两个显著特点。

2.2便捷的并发编程

毋庸置疑,Go语言对并发编程的支持是天生的、自然的和高效的。Go语言为此专门创造出了一个关键字“go”。使用这个关键字,我们就可以很容易的使一个函数被并发的执行。就像这样:

go func() {
  fmt.Println("Concurrent execution!")
}()

上面的这段代码使用关键字“go”并发的执行了一个匿名函数,虽然这个匿名函数只会在标准输出上打印一句话而已。更确切地说,该匿名函数会在一个单独的Goroutine中(或称Go程)被执行。我们把“go”和跟在它后面的函数以及调用符号“(”和“)”合称为go语句,而把那个匿名函数称为go函数。

如果我们要在不同的Goroutine中运行的函数之间传递数据,那么我们可以使用Channel(也可称其为通道)。这也是Go语言强烈推荐的做法。

我们可以用程序模仿自来水厂的净水设施。这个净水设施会引导水流先后流经三个净水装置,最后产出可饮用的自来水。为了更好理解,我们用过滤数字来代表对水的过滤。

我们构建两个数字过滤装置、一个数字输出装置和三个数字通道。下面是三个数字通道的创建和初始化代码:

numberChan1 := make(chan int64, 3) // 数字通道1。
numberChan2 := make(chan int64, 3) // 数字通道2。
numberChan3 := make(chan int64, 3) // 数字通道3。

Go语言的内建函数make可以用于创建和初始化一个通道。我们在这里定义,通道的元素类型都是int64,而长度都是3。另外,特殊标记“:=”可被用来在函数中声明并初始化变量。这种情况下,我们可以省略掉变量的类型的声明。

这里有一点需要特别说明,运行main函数的Goroutine(也被称为主Goroutine)会一条接一条地执行main函数中的语句,不论这些语句中是否存在以及有多少条go语句。换句话说,主Goroutine并不会等到其他被启用的Goroutine运行结束之后再结束自身的运行。因此,如果我们不采取任何措施的话,很可能在欲执行的go函数得到执行机会之前主Goroutine就已经结束运行了。一旦如此,当前程序的执行也就会宣告结束。这也意味着,那些go函数中的语句根本就不会被执行。

所以,我们在这里需要再声明一个变量,并稍微设置一下。这个变量代表了一个同步工具。对它的合理运用可以避免上述情况的发生。对这个变量的声明和初始化的代码如下:

var waitGroup sync.WaitGroup // 用于等待一组操作执行完毕的同步工具。
waitGroup.Add(3)              // 该组操作的数量是3。

标识符sync.WaitGroup代表了一个类型。该类型的声明存在于代码包sync中,类型名为WaitGroup。另外,上面的第二条语句预示着我们将要后面启用三个Goroutine,或者说要并发的执行三个go函数。请记住,我们在这里进行了一个“加3”的操作。

我们下面依次展现这三个go函数,并说明它们的功用。先来看第一个go函数,包含它的go语句如下:

go func() { // 数字过滤装置1。
  for n := range numberChan1 { // 不断的从数字通道1中接收数字,直到该通道关闭。
    if n%2 == 0 { // 仅当数字可以被2整除,才将其发送到数字通道2.
      numberChan2 <- n
    } else {
      fmt.Printf("Filter %d. [filter 1]\n", n)
    }
  }     
  close(numberChan2) // 关闭数字通道2。
  waitGroup.Done()   // 表示一个操作完成。
}()

这段代码代表了数字装置1的功能。下面是对其中的go函数的解释:

  • 函数的第一条语句为for语句。它会不停的从数字通道numberChan1中接收元素值(在这里是数字)并进行处理,直到numberChan1被关闭。
  • 只有可以被2整除的数才可以被送往数字通道numberChan2,否则就会被过滤掉。为了方便查看,我们每过滤一个数字都会打印出一句话。
  • 符号“<-”被称为接收操作符。在这里,它会把标识符n代表的数字发送给数字通道numberChan2。
  • 由于numberChan1通道的关闭会使这里的for语句结束执行。这意味着上游不会再有任何数字“流出”。所以,我们在这条for语句的后面顺势关闭通道numberChan2。这也是为了告诉它的下游,没有更多的数字需要被过滤了。
  • 对waitGroup的Done方法的调用表示了数字装置1已经完成了所有工作。该方法会进行相应的“减1”操作。请记住它,我们后面会对此进行说明。

我们完成了数字过滤装置1的编写。数字过滤装置2的功能与此如出一辙。只不过它会过滤掉不能被5整除的数字。大家应该可以仿照上面的代码写出数字过滤装置2的实现代码。注意,数字过滤装置2会试图从数字通道numberChan2中接收数字,并将未被过滤的数字发送给数字通道numberChan3。如此一来,数字过滤装置1和2就经由数字通道2串联起来了。请注意,不要忘记在数字过滤装置2中的for语句后面添加对数字通道numberChan3的关闭操作,以及调用waitGroup变量的Done方法。这非常重要。

现在我们来看数字输出装置。它即由第三条go语句代表。以下是具体代码:

go func() { // 数字输出装置。
  for n := range numberChan3 { // 不断的从数字通道3中接收数字,直到该通道关闭。
    fmt.Println(n) // 打印数字。
  }
  waitGroup.Done() // 表示一个操作完成。
}()

这个go函数的功能就非常简单了。它只是打印出“通过净化”的数字。不过,waitGroup.Done()语句依然被包含在内。

好了,我们已经编写出了所有的装置,并合理运用了那三个数字通道。有一点值得说明,到相应的数字通道中没有任何数字可取时,for语句的执行会被阻塞。也正因为如此,我们可以把这三条go语句放置在前,并在之后激活这一过滤数字的流程。具体的激活方法是,向数字通道numberChan1发送数字。相关的代码如下:

for i := 0; i < 100; i++ { // 先后向数字通道1传送100个范围在[0,100)的随机数。
  numberChan1 <- rand.Int63n(100)
}
close(numberChan1) // 数字发送完毕,关闭数字通道1。

这段代码的意图很明显。我们先向数字通道numberChan1发送100个随机数,然后关闭numberChan1通道以表示所有需要过滤的数字都发送完毕。放心,对通道的关闭并不会影响到对已存于其中的数字的接收操作。

好了,我们至此实现了一个完整的数字过滤流程。为了能够让这个流程能够被完整的执行,我们还需要在最后加入这样一条语句:

waitGroup.Wait() // 等待前面那组操作(共3个)的完成。

对waitGroup的Wait方法的调用会一直被阻塞,直到前面三个go函数中的三个waitGroup.Done()语句(即那三个“减1操作”)都被执行完毕。“加3”操作使变量waitGroup的状态有所改变,并以此阻塞住了之后的waitGroup.Wait()语句的执行。而后续被并发执行的三个“减1”操作的执行又使变量waitGroup的状态回归初始。这才能让对waitGroup.Wait()语句的执行从阻塞中恢复并完成。这是防止主Goroutine过早的被运行结束的有效手段之一。

下面是一幅可以宏观的展示数字过滤流程的图示。

图1-1 数字过滤流程

我们把上述代码都放入到一个命令源码文件的main函数中。并在文件的开始处添加一条代码包导入语句:

import (
  "fmt"
  "math/rand"
  "sync"
)

大家可以试着使用“go run”命令运行这个命令源码文件,并观察输出结果。

我们配合使用Goroutine和Channel让数字过滤流程实现了全异步化,但却没有增加开发的难度。Channel可以让我们以管道的方式在多个Goroutine之间交换数据。这也恰恰实践和印证了这句话:

Do not communicate by sharing memory; instead, share memory by communicating.

在这之中起到关键作用的Channel有着非常灵活、多样的使用方法。在后续的文章中,我会专门就此进行论述。

虽然我们可以使用其他语言的代码实现这样的异步化,但是它们不会像Go语言这样为此提供语言级别的原生支持。也正是由于这个原因,那些代码会看起来复杂得多。它们不得不使用若干个类库或辅助工具来满足异步化的要求。另一方面,Go语言先进、高效的并发编程模型及其实现系统会使得程序对系统资源的消耗大大减少,并且会在很大程度上提高对这些资源的使用效率。这一优势是很多其他语言望尘莫及的。同样,我会在后面简明扼要的说明Goroutine的运作机理。

3. Go语言的哲学

通过对前面内容的阅读,大家应该能够隐约的感觉到Go语言的关注点,以及它想为软件开发者们带来的启示和新思想。

作为本篇文章的总结,我在下面列出几点最重要的Go语言的哲学:

  1. Go语言集众多编程范式之所长,并以自己独到的方式将它们融合在一起。程序员们可以用他们喜欢的风格去设计程序。
  2. 相对于设计规则上的灵活,Go语言有着明确且近乎严格的编码规范。我们可以通过“go fmt”命令来按照官方的规范格式化代码。
  3. Go语言是强调软件工程的编程语言。它自带了非常丰富的标准命令,涵盖了软件生命周期(开发、测试、部署、维护等等)的各个环节。
  4. Go语言是云计算时代的编程语言。它关注高并发程序,并旨在开发效率和运行效率上取得平衡。
  5. Go语言提倡交换数据,而不是共享数据。它的并发原语Goroutine和Channel是其中的两大并发编程利器。同时,Go语言也提供了丰富的同步工具,以供程序员们根据场景选用。然而,后者就不属于语言级别的支持了。
最全的Go按照开发流程 Go是2009年开源的编程语言,Go语言具有以下特性:语法简洁、并发编程、编译迅速、数组安全、丰富的内置类型、错误处理、匿名函数和闭包、反射、函数多返回值、自动垃圾回收。**Go语言标识符与其它语言类似,第一个字符必须是字母、下划线,不能是数字。2、关键字Go语言的25个关键字或者保留字:Go语言的36个预定义标识符: 阅读详情

相关推荐

Go语言全面解析:从入门到精通

Go语言是由Google开发的一种静态类型、编译型编程语言,具有简洁、高效、安全的特点。它特别适合高并发服务、云原生应用和网络编程等场景。Go采用Goroutine和Channel实现轻量级并发,性能接近C/C++。与其他语言相比,Go语法更简洁但类型更严格,编译速度快且跨平台支持好。虽然Go支持多种设计模式和编程范式,但其面向对象实现方式与传统语言不同。标准库丰富且拥有Gin、GORM等企业级框架。核心语法包括包管理、变量声明、函数定义、流程控制等,适合构建高性能后端服务和系统工具。

博哥哥的博客 4925

Go语言详解

Go(The Google Programming Language)语言是谷歌2009年发布的第二款开源编程语言。Go语言专门针对多处理器系统应用程序的编程进行了优化,使用Go编译的程序可以媲美C或C++代码的速度,而且更加安全、支持并行进程。Go支持面向对象,而且具有真正的闭包(closures)和反射 (reflection)等功能。 特色 简洁 快速 安全 并行 有趣 ...

顺其自然~专栏 3万+

Android双目摄像头(RGB+IR)实时预览与人脸活体检测实战指南

本文详细介绍了Android双目摄像头(RGB+IR)实时预览与人脸活体检测的实战指南。通过双摄同步预览、人脸检测与活体判断等技术实现,提升安全认证的准确性和鲁棒性。文章还提供了开发环境搭建、常见问题解决方案及性能优化建议,帮助开发者快速掌握双目摄像头在Android平台的应用。

vulkan6gpu的博客 691

Go语言超全详解(入门级)

Go语言是谷歌2009年发布的第二款开源编程语言(系统开发语言),它是基于编译、垃圾收集和并发的编程语言。 Go语言专门针对多处理器系统应用程序的编程进行了优化,使用Go编译的程序可以媲美 C / C++代码的速度,而且更加安全、支持并行进程......

weixin_50941083的博客 14万+

别再死磕官方文档了!用宿舍开黑的故事,5分钟搞懂Autosar CanNM网管报文

本文通过宿舍开黑游戏的生动类比,深入浅出地解析了Autosar CanNM网管报文的工作原理。从游戏队友协作到汽车ECU节点的同步机制,详细介绍了网管报文的唤醒流程、通信协议及休眠策略,帮助读者快速掌握这一关键技术。

weixin_30463341的博客 262

【YOLOv11】从零搭建基于YOLOv11深度学习算法的农作物虫害检测系统(附带环境搭建+完整代码+讲解)

《基于YOLOv11的农作物病虫害智能检测系统》项目摘要 本项目开发了一个基于YOLOv11深度学习算法的农作物病虫害检测系统,支持玉米、水稻、草莓和西红柿等四大类经济作物的30多种病虫害识别。系统采用多模态检测方式,支持图片、视频和实时摄像头输入,并集成了完整的Web应用框架。 技术架构上,系统以PyTorch实现YOLOv11算法为核心,结合Flask搭建深度学习服务,SpringBoot构建业务后端,Vue3+TypeScript开发前端界面,MySQL数据库存储检测数据。系统具备用户权限管理功能,支

AnChenliang_1002的博客 812

Go语言核心编程---02Golang的概述

文章目录2.1 Go语言的特点2.2 Go语言开发工具(Mac版本)2.3 Golang执行流程分析2.4 Go程序开发注意事项2.5 Go语言的转义字符2.6 Golang中的注释形式2.7 规范的代码风格2.8 Golang标准库API文档 2.1 Go语言的特点 Go语言保证了技能到达静态编译语言的安全和性能,又打到了动态语言开发维护的高效率,使用一个表达式来形容Go语言,Go = C + ...

luyangsiyi的博客 459

Open3D(C++) 点云构建三维Delaunay三角剖分

C++版本的Open3D实现从点云构建三维Delaunay,可视化效果。

点云侠的博客 2247

非零基础自学Golang 第1章 走进Go 1.1 Go编程语言概述 1.1.3 使用Go 语言的项目

非零基础自学Golang 第1章 走进Go 1.1 Go编程语言概述 1.1.3 使用Go 语言的项目

代码改变世界 542

量化之趋势跟踪策略

趋势跟踪策略 import numpy as np import pandas as pd import matplotlib as mpl import matplotlib.pyplot as plt import seaborn as sns from finance import GetData import warnings; warnings.filterwarnings('ignore') data = GetData.get_data('../data/002236.csv') .

木头大左的博客 2533

【技能】伪真openclaw主动式智能体—告别‘巨婴’AI工具人:体验主动智能体的魅力

摘要: 传统AI常因被动执行、缺乏闭环而令人抓狂。Proactivity主动执行能力将AI从"指令跟随者"升级为"主动合伙人",具备预判需求、自动推进、断聊恢复、问题自解等能力。其核心原理在于建立AI专属工作体系(持久化内存、动态任务层、临时缓存层、归档复盘层),通过7步闭环(感知触发→状态恢复→边界校验→方案探索→动作决策→执行落地→状态留存)确保安全高效。

海兰 209

golang快速入门[5.2]-go语言是如何运行的-内存概述

前文 golang快速入门[2.1]-go语言开发环境配置-windows golang快速入门[2.2]-go语言开发环境配置-macOS golang快速入门[2.3]-go语言开发环境配置-linux golang快速入门[3]-go语言helloworld golang快速入门[4]-go语言如何编译为机器码 golang快速入门[5.1]-go语言是如何运行的-链接器 前言 ...

weishixianglian的博客 436

BevFusion (1): 传感器介绍

激光雷达,也称光学雷达(LIght Detection And Ranging)是激光探测与测距系统的简称,它通过测定传感器发射器与目标物体之间的传播距离,分析目标物体表面的反射能量大小、反射波谱的幅度、频率和相位等信息,从而呈现出目标物精确的三维结构信息。激光雷达是自动驾驶车辆的关键传感器,如下图所示,车辆上方旋转的圆柱体对应就是激光雷达传感器。

@bangbang的博客 1475

非零基础自学Golang 第1章 走进Go 1.1 Go编程语言概述 1.1.1 Go 的历史

非零基础自学Golang 第1章 走进Go 1.1 Go编程语言概述 1.1.1 Go 的历史

代码改变世界 660

jre9下载 jdk9

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

Data-Structures-and-Algorithm-Analysis-in-Java.pdf

作者: Weiss, Mark A. 出版社: Addison Wesley Data Structures and Algorithm Analysis in Java is an “advanced algorithms” book that fits between traditional CS2 and Algorithms Analysis courses. In the old ACM Curriculum Guidelines, this course was known as CS7. This text is for readers who want to learn good programming and algorithm analysis skills simultaneously so that they can develop such programs with the maximum amo...

linux go 禁用 debug_golang快速入门[5.2]go语言是如何运行的内存概述

前言总的来说一个程序的生命周期可以概括为: 编写代码 => 编译 => 链接 => 加载到内存 => 执行在上一篇文章中,我们详细介绍了go语言编译链接的过程在本文中,我们将对内存进行简单介绍在下文中,我们将介绍内存分配以及go语言中的内存分配内存在计算机中,术语"内存"又叫做主存,通常指的是可寻址的半导体存储器(硅基MOS晶体管组成的集成电路)内存有易失性(vo...

weixin_36166342的博客 253

SAP B1中文培訓教材_SDK

公司内部培训资料,对开发工具 ,DIAPI, UIAPI,Add-ON有详细解说

Go语言学习札记——第一章 Go语言概述

Normal 0 7.8 磅 0 2 false false false MicrosoftInternetExplorer4 <object class

savechina的专栏 6957

golang 关闭gc 并手动gc_go语言的垃圾回收(GC)概述

垃圾回收是高级语言的一个进步,其算法目前有几种经典的算法,说go的GC之前先说一下所有的GC的算法:引用计算法:每一个对象都有一个计数器,当这个对象被引用一次时,计数器加一,减少一次引用时,计数器减一,这样当对象的计数器为0时,我们就可以进行回收了。PHP、Object等在使用。优点:回收快,算法简单,不需要STW(Stop The World,挂起程序)缺点:相互引用时无法回收,计数器增加消耗。...

weixin_42504279的博客 941

golang mysql 死锁_Go语言死锁、活锁和饥饿概述

typevaluestruct{musync.Mutexvalueint}varwgsync.WaitGroupprintSum:=func(v1,v2*value){deferwg.Done()v1.mu.Lock()//在这里,我们尝试进入临界区来传入一个值。deferv1.mu.Unlock()//在这里,我们使用defer语句在printSum返回之前退出临界区。time.Sleep(2*...

weixin_33982355的博客 319

C++GO语言微服务项目之go语言概述

C++GO语言微服务项目之go语言概述

qq_27302885的博客 903

linux go 禁用 debug_golang快速入门[5.2]-go语言是如何运行的-内存概述

前文golang快速入门[2.1]-go语言开发环境配置-windowsgolang快速入门[2.2]-go语言开发环境配置-macOSgolang快速入门[2.3]-go语言开发环境配置-linuxgolang快速入门[3]-go语言helloworldgolang快速入门[4]-go语言如何编译为机器码golang快速入门[5.1]-go语言是如何运行的-链接器前言总的来说一个程序的生命周期可...

weixin_39924179的博客 148

Go 语言概述 (下)

Go 语言概述 (下) 函数 定义函数 main.go package main import ( "fmt" ) func main() { fmt.Println(add(1, 2)) } func add(a int, b int) (int) { return a + b } 注: 前几个函数参数的类型可以省略, 最后一个不行. fun

风格色的博客 506

从零到一学习golang语言_初识go语言(一)

从本篇文章起,从零到一学习go语言。 一、go和golang? 到底是go语言还是golang语言,其实官网已经表态过为go语言。官网的域名使用https://golang.org/,是因为go.org已经被注册过了,需要花几千万购买,但是没这个必要。第二个原因使用golang是因为,在搜索引擎中查找相关go的资料时使用golang能能更大限度匹配,如果仅仅是输入go很可能得不到你想要的。 二、go语言简介 go语言是一个开源的项目,为了让程序开发者更高产,提高程序员的开发生产力。 go语言富有表

Sun_ltyy的博客 1355

Go语言概述

1)从语言层面支持并发,实现简单2)goroutine,轻量级线程,可实现大并发处理,高效利用多核3)垃圾回收机制,内存自动回收,不需要开发人员管理4)5)吸收了管道通信机制,形成Go语言特有的管道channel,通过管道channel,可以实现不同的goroute之间的相互通信。6)函数返回多个值。

对我来说痴心绝对的博客 649

非零基础自学Golang 第1章 走进Go 1.1 Go编程语言概述 1.1.2 Go 语言特性及应用场景

非零基础自学Golang 第1章 走进Go 1.1 Go编程语言概述 1.1.2 Go 语言特性及应用场景

代码改变世界 586
上一篇: IOS 服务评测
下一篇: 机器学习-分类简介
张哲BJUT
博客等级 码龄15年 151粉丝 111原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值