4 异常机制--数组、切片、算法【Go语言教程】

news2025/1/10 4:55:41

4 异常机制–数组、切片、算法【Go语言教程】

1 异常机制

1.1 处理错误

  1. Go 语言追求简洁优雅,所以,Go 语言不支持传统的 try…catch…finally 这种处理。
  2. Go 中引入的处理方式为:defer, panic, recover
  3. 这几个异常的使用场景可以这么简单描述:Go 中可以抛出一个 panic 的异常,然后在 defer 中通过 recover 捕获这个异常,然后正常处理
package main
import (
	"fmt"
	_ "time"
)

func test(){
	//使用defer + recover 来捕获和处理异常
	defer func(){
		err := recover() //recover()内置函数,可以捕获到异常
		if err != nil { //说明捕获到异常
			fmt.Println("err=", err)
			//这里就可以将错误信息发送给管理员
			fmt.Println("发送邮件给admin@sohu.com~")
		}
	}()
	num1 := 10
	num2 := 0
	res := num1 / num2
	fmt.Println("res=", res)
}

func main(){
	test()
}

在这里插入图片描述

1.2 自定义错误

Go 程序中,也支持自定义错误, 使用 errors.New 和 panic 内置函数。

  1. errors.New(“错误说明”) , 会返回一个 error 类型的值,表示一个错误
  2. panic 内置函数 ,接收一个 interface{}类型的值(也就是任何值了)作为参数。可以接收 error 类型的变量,输出错误信息,并退出程序.
package main
import (
	"fmt"
	"errors"
)

//函数去读取配置文件init.conf的信息
//如果文件名传入不正确,我们就返回一个自定义的错误

func readConf(name string) (err error){
	if name == "config.ini" {
		//读取...
		return nil
	}else {
		//返回一个自定义的错误
		return errors.New("读取文件错误")
	}
}

func test02(){
	err := readConf("config2.ini")
	if err != nil {
		//如果读取文件发送错误,就输出这个错误,并终止程序
		panic(err)
	}
	fmt.Println("test02()继续执行")
}

func main(){
	//测试自定义错误的使用
	test02()
}

在这里插入图片描述

2 数组与切片

2.1 数组

2.1.1 概念

数组可以存放多个同一类型数据。数组也是一种数据类型,在 Go 中,数组是值类型。
注意:数组的地址就是数组第一个元素的地址;我们可以通过地址(根据数据类型推断,如:int64,数组地址为0x428170,则数组第二个元素地址为0x428178,int64占8字节)来更加快速的访问到数组中元素的值

在这里插入图片描述

  1. 数组的地址可以通过数组名来获取 &intArr
  2. 数组的第一个元素的地址,就是数组的首地址
  3. 数组的各个元素的地址间隔是依据数组的类型决定,比如 int64 -> 8 int32->4…

在这里插入图片描述

2.1.2 初始化方式及使用

  • 初始化方式:
package main
import (
	"fmt"
)


func main(){
	//四种初始化数组的方式
	var numArr01 [3]int = [3]int{1,2,3}
	fmt.Println("numArr01=", numArr01)

	var numArr02 = [3]int{5,6,7}
	fmt.Println("numArr02=", numArr02)

	var numArr03 = [...]int{8,9,10}
	fmt.Println("numArr03=", numArr03)

	//指定对应下标的元素
	var numArr04 = [...]int{1:800, 0: 900, 2:999}
	fmt.Println("numArr04=", numArr04)

	//类型推导
	strArr05 := [...]string{1:"tom", 0:"jack", 2:"mary"}
	fmt.Println("strArr05=", strArr05)
}

在这里插入图片描述

  • 数组的使用:

从终端循环输入 5 个成绩,保存到 float64 数组,并输出.

package main
import (
	"fmt"
)


func main(){
	//从终端输入5个成绩,并保存到float64数组
	var scores [5]float64
	for i := 0; i < len(scores); i++ {
		fmt.Printf("请输入第%d个元素的值\n", i+1)
		fmt.Scanln(&scores[i])
	}
	//打印结果
	for i := 0; i < len(scores); i++ {
		fmt.Printf("scores[%d]=%v\n", i, scores[i])
	}
}

在这里插入图片描述

2.1.3 遍历方式及使用细节

①遍历方式:

package main
import (
	"fmt"
)


func main(){
	arr := [4]int {1, 2, 3, 4}
	//1. 常规遍历方式
	fmt.Println("==========第一种遍历方式============")
	for i := 0; i < len(arr); i++ {
		fmt.Println(arr[i])
	}
	//2. for-range遍历
	fmt.Println("==========for-range============")
	for _, v := range arr {
		fmt.Println(v)
	}
}

在这里插入图片描述
②使用细节

  1. 数组是多个相同类型数据的组合,一个数组一旦声明/定义了,其长度是固定的, 不能动态变化
  2. var arr []int 这时 arr 就是一个 slice 切片
  3. 数组中的元素可以是任何数据类型,包括值类型和引用类型,但是不能混用。
  4. 数组创建后,如果没有赋值,有默认值(零值)
    数值类型数组:默认值为 0
    字符串数组: 默认值为 “”
    bool 数组: 默认值为 false
  5. 数组下标必须在指定范围内使用,否则报 panic:数组越界
  6. Go 的数组属值类型, 在默认情况下是值传递, 因此会进行值拷贝。数组间不会相互影响
    在这里插入图片描述
  7. 如想在其它函数中,去修改原来的数组,可以使用引用传递(指针方式)
    在这里插入图片描述

2.2 切片

2.2.1 概念

先看一个需求:我们需要一个数组用于保存学生的成绩,但是学生的个数是不确定的,请问怎么办?解决方案:-》使用切片。【类比于java中的list集合】

  1. 切片的英文是 slice
  2. 切片是数组的一个引用,因此切片是引用类型,在进行传递时,遵守引用传递的机制。
  3. 切片的使用和数组类似,遍历切片、访问切片的元素和求切片长度 len(slice)都一样。
  4. 切片的长度是可以变化的,因此切片是一个可以动态变化数组。
  5. 切片定义的基本语法: var 切片名 []类型 比如:var a [] int

2.2.2 使用

方式一:

定义一个切片,然后让切片去引用一个已经创建好的数组,比如下面的案例就是这样的。

package main
import (
	"fmt"
)


func main(){
	//演示切片的基本使用
	var intArr [5]int = [...]int{1,2,44,55,99}
	//声明/定义一个切片
	//slice := intArr[1:3]
	//1. slice就是切片名
	//2. intArr[1:3] 表示slice引用到intArr这个数组
	//3. 引用intArr数组的起始下标为1, 最后的下标为3(但是不包含3)
	slice := intArr[1:3]
	fmt.Println("intArr=", intArr)
	fmt.Println("slice的元素是=", slice)
	fmt.Println("slice的元素个数是=", len(slice))
	fmt.Println("slice的容量是=", cap(slice))//切片的容量是可以动态变化的
}

在这里插入图片描述
方式二:

通过 make 来创建切片.

  • 语法:var 切片名 []type = make([]type, len, [cap])
    参数说明: type: 就是数据类型 len : 大小 cap :指定切片容量,可选, 如果你分配了 cap,则要求 cap>=len.
    在这里插入图片描述

对上面代码的小结:

  1. 通过 make 方式创建切片可以指定切片的大小和容量
  2. 如果没有给切片的各个元素赋值,那么就会使用默认值[int , float=> 0 string =>”” bool => false]
  3. 通过 make 方式创建的切片对应的数组是由 make 底层维护,对外不可见,即只能通过 slice 去访问各个元素.

方式三:

定义一个切片,直接就指定具体数组,使用原理类似 make 的方式
在这里插入图片描述

面试:方式一与方式二的区别:
在这里插入图片描述

三种方式创建全部代码:

package main
import (
	"fmt"
)


func main(){
	arr1 := [...]int {1,4,5,2,7}
	//方式1:直接引用数组(切片的变化会影响原来数组的变化)
	slice1 := arr1[:3]//0:3
	fmt.Println("slice1=", slice1)

	//方式2:通过make
	//对于切片来说如果不是通过数组直接引用,那么必须make后(开辟内存空间)使用
	var slice2 []float64 = make([]float64, 5, 10)
	slice2[1] = 10
	slice2[3] = 20
	fmt.Println("slice2=", slice2)

	//方式3:直接指定具体数组【原理类似于make的方式】
	var slice3 []string = []string{"tom", "jack", "mary"}
	fmt.Println("slice3=", slice3)
	fmt.Println("slice3 size=", len(slice3))
	fmt.Println("slice3 cap=", cap(slice3))	
}

在这里插入图片描述

2.2.3 切片在内存中的形式(重要)

在这里插入图片描述

对上面的分析图总结

  1. slice 的确是一个引用类型
  2. slice 从底层来说,其实就是一个数据结构(struct 结构体)
  3. type slice struct {
    ptr *[2]int
    len int
    cap int

}

2.2.4 切片的遍历

切片的遍历和数组一样,也有两种方式

  • for 循环常规方式遍历
  • for-range 结构遍历切片
func main(){
	slice := [3]int {1, 2, 4}
	//常规for
	for i := 0; i < len(slice); i++ {
		fmt.Printf("slice[%v]=%v", i, slice[i])
	}

	fmt.Println()
	//使用for-range 方式遍历 i:index, v:value
	for i, v := range slice {
		fmt.Printf("i=%v v=%v\n", i, v)
	}
}

2.2.5 切片的使用细节

  1. 切片初始化时 var slice = arr[startIndex:endIndex]
    说明:从 arr 数组下标为 startIndex,取到 下标为 endIndex 的元素(不含 arr[endIndex])。
  2. 切片初始化时,仍然不能越界。范围在 [0-len(arr)] 之间,但是可以动态增长.
  • var slice = arr[0:end] 可以简写 var slice = arr[:end]
  • var slice = arr[start:len(arr)] 可以简写: var slice = arr[start:]
  • var slice = arr[0:len(arr)] 可以简写: var slice = arr[:]
  1. cap 是一个内置函数,用于统计切片的容量,即最大可以存放多少个元素。
  2. 切片定义完后,还不能使用,因为本身是一个空的,需要让其引用到一个数组,或者 make 一个空间供切片来使用
  3. 切片可以继续切片
    在这里插入图片描述
  4. 用 append 内置函数,可以对切片进行动态追加
    在这里插入图片描述
package main
import (
	"fmt"
)


func main(){
	slice1 := [...]int {1, 2, 4, 6, 9, 10, 57, 28}
	slice2 := slice1[2:5]
	fmt.Println("slice2=", slice2)
	slice2[0] = -39
	fmt.Println("slice1=", slice1)
	fmt.Println("slice2=", slice2)
	//append()追加
	slice2 = append(slice2, -100, -200)
	fmt.Println("追加后的slice2=", slice2)
}

在这里插入图片描述
在这里插入图片描述

切片 append 操作的底层原理分析:

  • 切片 append 操作的本质就是对数组扩容
  • go 底层会创建一下新的数组 newArr(安装扩容后大小)
  • 将 slice 原来包含的元素拷贝到新的数组 newArr slice 重新引用到 newArr
    注意 :newArr 是在底层来维护的,程序员不可见.
  1. 切片的拷贝操作
    切片使用 copy 内置函数完成拷贝
    在这里插入图片描述
    (1) copy(para1, para2) 参数的数据类型是切片
    (2) 按照上面的代码来看, slice4 和 slice5 的数据空间是独立,相互不影响,也就是说 slice4[0]= 999, slice5[0] 仍然是 1
  2. 关于拷贝的注意事项
    在这里插入图片描述
    说明: 上面的代码没有问题,可以运行, 最后输出的是 [1]
func main(){
	slice1 := []int {1,2,5,6,7}
	var slice2 = make([]int, 1)
	copy(slice2, slice1)
	//slice2= [1]
	fmt.Println("slice2=", slice2)
}
  1. 切片是引用类型,所以在传递时,遵守引用传递机制。看两段代码,并分析底层原理
    在这里插入图片描述

2.2.6 string与slice

  1. string 底层是一个 byte 数组,因此 string 也可以进行切片处理
  2. string 和切片在内存的形式,以 “abcd” 画出内存示意图
  3. string 是不可变的,也就说不能通过 str[0] = ‘z’ 方式来修改字符串
  4. 如果需要修改字符串,可以先将 string -> []byte / 或者 []rune -> 修改 -> 重写转成 string
func main(){
	//1.不含有中文的字符串修改
	str := "hello, china"
	arr1 := []byte(str)
	arr1[0] = 'z'
	str = string(arr1)
	fmt.Println("str=", str)

	//2.含中文的字符串修改
	str2 := "你好, 你在哪里a"
	arr2 := []rune(str2)
	arr2[0] = '北'
	str2 = string(arr2)
	fmt.Println("str2=", str2)
	// str= zello, china
	// str2= 北好, 你在哪里a

}

2.2.7 实现斐波那契数列

说明:编写一个函数 fbn(n int) ,要求完成

  1. 可以接收一个 n int
  2. 能够将斐波那契的数列放到切片中
  3. 提示, 斐波那契的数列形式:
    arr[0] = 1; arr[1] = 1; arr[2]=2; arr[3] = 3; arr[4]=5; arr[5]=8
//uint64范围更大
func fbn(n int)([] uint64){
	//声明一个切片,大小为n
	fbnSlice := make([]uint64, n)
	//初始化斐波那契,第一个、第二个数是1
	fbnSlice[0] = 1
	fbnSlice[1] = 1
	//进行for循环来存放斐波那契数列
	for i := 2; i < n; i++ {
		fbnSlice[i] = fbnSlice[i-1] + fbnSlice[i-2]
	}
	return fbnSlice
}

func main(){
	fbnSlice := fbn(10)
	//fbnSlice= [1 1 2 3 5 8 13 21 34 55]
	fmt.Println("fbnSlice=", fbnSlice)
}

3 算法

3.1 排序算法

冒泡排序:

//BubbleSort表示公开,其他包可以使用
//*[5]int 表示指针,可以修改数组的值
func BubbelSort(arr *[5]int){
	fmt.Println("排序前arr=", (*arr))
	tmp := 0 
	//冒泡排序【每一次找出最大的数来】
	for i := 0; i < len(*arr); i++ {
		for j := 0; j < len(*arr) - i - 1; j++ {
			if(*arr)[j] > (*arr)[j+1]{
				//交换
				tmp = (*arr)[j]
				(*arr)[j] = (*arr)[j+1]
				(*arr)[j+1] = tmp
			}
		}
	}
}

func main(){
	arr := [...]int {9,3,-1,0,87}
	BubbelSort(&arr)
	fmt.Println("排序后arr=", arr)
	//排序前arr= [9 3 -1 0 87]
	//排序后arr= [-1 0 3 9 87]
}

3.2 查找算法

二分查找

package main
import (
	"fmt"
)

//实现二分查找
func BinaryFind(arr *[6]int, target int) int {
	left := 0; right := len((*arr)) -1
	middle := left + (right - left) / 2
	for{
		if left <= right {
			middle = left + (right - left) / 2
			if (*arr)[middle] < target {
				left = middle + 1
			} else if (*arr)[middle] > target {
				right = middle - 1
			} else {
				return middle
			}
		}else {
			return -1
		}
	}
}


func main(){
	arr := [6]int{1,8,10,89,100,1234}
	res := BinaryFind(&arr, 1234)
	if res == -1 {
		fmt.Println("找不到")
	}else {
		fmt.Println("找到了,下标为:", res)
	}
}

3.3 二维数组

3.3.1 使用方式

方式一:

先声明/定义,再赋值

  • 语法: var 数组名 [大小][大小]类型
  • 比如: var arr [2][3]int , 再赋值。
  • 使用演示
  • 二维数组在内存的存在形式(重点)

在这里插入图片描述
在这里插入图片描述
方式二:

直接初始化

  • 声明:var 数组名 [大小][大小]类型 = [大小][大小]类型{{初值…},{初值…}}
  • 赋值(有默认值,比如 int 类型的就是 0)
  • 使用演示
    在这里插入图片描述说明:二维数组在声明/定义时也对应有四种写法[和一维数组类似]
  1. var 数组名 [大小][大小]类型 = [大小][大小]类型{{初值…},{初值…}}
  2. var 数组名 [大小][大小]类型 = […][大小]类型{{初值…},{初值…}}
  3. var 数组名 = [大小][大小]类型{{初值…},{初值…}}
  4. var 数组名 = […][大小]类型{{初值…},{初值…}}

3.3.2 遍历方式

  • 双层 for 循环完成遍历
  • for-range 方式完成遍历

在这里插入图片描述

package main
import (
	"fmt"
)

func main(){
	//演示二维数组的遍历
	var arr = [2][3]int{{1,2,3},{4,5,6}}
	//1. 双重for循环
	for i := 0; i < len(arr); i++ {
		for j := 0; j < len(arr[i]); j++ {
			fmt.Printf("%v\t", arr[i][j])
		}
		fmt.Println()
	}

	//2. for-range方式遍历
	for i, v := range arr {
		for j, v2 := range v {
			fmt.Printf("arr[%v][%v]=%v \t", i, j, v2)
		}
		fmt.Println()
	}
}

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/482767.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【小沐学Python】Python实现Web服务器(Flask框架扩展:Flask-Admin)

文章目录 1、简介1.1 flask1.2 flask-admin 2、安装2.1 安装库2.2 打印库版本 3、初始化4、添加独立视图&#xff08;BaseView&#xff09;4.1 管理接口索引页4.2 自定义视图 5、添加模型视图&#xff08;ModelView&#xff09;6、添加特殊视图6.1 Managing Files & Folder…

VS2019配置redis客户端的c++开发环境

目录 需要的开源库&#xff1a; 具体步骤&#xff1a; 遇到的问题&#xff1a; 1. 确保每个项目使用的配置解决方案管理器一样 2.CMAKE 的安装 3. 使用 CMAKE 的路径配置 4. redis 编译报错&#xff1a;jemalloc/jemalloc.h没有这个文件&#xff0c;或者找不到.dll 5. linux …

【Linux】初识Linux --指令Ⅰ

Halo&#xff0c;这里是Ppeua。平时主要更新C语言&#xff0c;C&#xff0c;数据结构算法&#xff0c;Linux…感兴趣就关注我吧&#xff01;你定不会失望。 目录 1.ls 显示当前目录下的文件内内容2.pwd-显示用户当前所在的目录3.cd-改变工作目录。将当前工作目录改变到指定的目…

C++ STL-deque

deque&#xff1a;双端队列 目录 deque&#xff1a;双端队列 1、 基本介绍 2、使用方法 2.1、 头文件 2.2、 定义 2.3、 方法函数 3、排序 1、 基本介绍 首尾都可插入和删除的队列为双端队列。 deque容器是连续的空间&#xff0c;其他连续的行空间还有 array 和 vect…

E. Multihedgehog(多叉树找root节点)

Problem - E - Codeforces 有人给Ivan一个奇怪的生日礼物&#xff0c;这是一只刺猬 - 一个连通的无向图&#xff0c;其中一个顶点的度至少为3&#xff08;我们称其为中心&#xff09;&#xff0c;而所有其他顶点的度数均为1。Ivan认为刺猬太无聊了&#xff0c;决定自己制造k-多…

总结838

四月结束&#xff0c;五月来临。又到了月度总结与规划的时候了。 四月总结&#xff1a;高等数学原计划复习完18讲内容&#xff0c;刷完对应的习题。如今还剩三讲&#xff0c;本可以看完&#xff0c;但因为后面分专题了&#xff0c;还没确定是数1还是数2.所以耽搁了一下。英语原…

SG函数(博弈论)

一&#xff0c;定义 对于满足以下条件的公平二人游戏&#xff0c;均可以用sg函数&#xff08;暴搜&#xff09;获得答案 人数2人 两人交替进行合法操作&#xff0c;无法进行者LOSE对 于游戏的任意一种可能的局面&#xff0c;合法的操作集合只取决于这个局面的本身&#xff0c;…

掌握 Python 接口自动化测试理论,深度解读测试框架源码

目录&#xff1a;导读 引言 一、什么是接口测试、为什么要做接口测试 1、什么是接口测试 2、为什么要做接口测试 二、接口测试的流程 1、接口测试的流程 2、为什么要写测试用例 3、接口测试设计要点 三、python接口自动化-requests的应用 1、requests简介 2、reques…

Winform从入门到精通(37)——FolderBrowserDialog(史上最全)

文章目录 前言1、Name2、Description3、RootFolder4、SelectedPath5、ShowNewFolderButton前言 当需要获取一个可以通过用户自由选择路径的时候,这时候就需要FolderBrowserDialog控件 1、Name 获取FolderBrowserDialog对象 2、Description 用于指示对话框的描述,如下: …

Doris(22):Doris的函数—地理位置函数

1 ST_AsText(GEOMETRY geo) 将一个几何图形转化为WKT(Well Known Text)的表示形式 SELECT ST_AsText(ST_Point(24.7, 56.7)); 2 ST_Circle(DOUBLE center_lng, DOUBLE center_lat, DOUBLE radius) 将一个WKT(Well Known Text)转化为地球球面上的一个圆。其中center_lng表…

20230502 强化学习与反馈控制_利用自然决策方法设计最优自适应控制器

目录&#xff1a;强化学习与反馈控制_利用自然决策方法设计最优自适应控制器 总体介绍强化学习二级目录三级目录 总体介绍 本文描述了利用强化学习原理为离散和连续系统设计反馈控制器&#xff0c;该控制器结合了自适应控制和最优控制的特点。自适应控制和最优控制代表了设计反…

【ElasticSearch】EQL操作相关

文章目录 EQL操作基础语法数据准备数据窗口搜索统计符合条件的事件事件序列 安全检测数据准备查看数据导入情况获取 regsvr32 事件的计数检查命令行参数检查恶意脚本加载检查攻击成功可能性 EQL操作 EQL 的全名是 Event Query Language (EQL)。事件查询语言&#xff08;EQL&…

Meta财报预测:市场悲观情绪被过度放大,Meta股价未来将强势反弹

来源&#xff1a;猛兽财经 作者&#xff1a;猛兽财经 4月26日收盘后&#xff0c;Meta(META)将发布2023年第一季度财报。由于全球在线广告支出的减少给Meta这样的广告平台带来了很大的压力&#xff0c;市场对Meta的投资情绪非常悲观&#xff0c;华尔街分析师也预测&#xff0c;…

chatGPT免登录的版本哪里有啊

ChatGPT免费次数 Chat GPT 模型通常通过 API 或 SDK 的方式进行使用&#xff0c;并且有一定的免费使用次数或免费试用期&#xff0c;以便用户可以在部分场景下了解模型的性能和效果。但是&#xff0c;每个机器学习平台或服务商的免费使用次数和试用期都可能不同&#xff0c;您…

ChatGPT回复中断的原因-chatGPT国内中文版免费

ChatGPT回复中断怎么办啊 如果您使用ChatGPT时遇到了中断或错误&#xff0c;以下是一些可能有用的解决方案&#xff1a; 检查输入是否正常&#xff1a;输入文本是否符合语法规范和限制条件&#xff0c;例如输入文本长度是否超过了模型限制等等。如果输入不符合要求&#xff0c…

pikachu靶场-Unsafe Filedownload

不安全的文件下载 文件下载功能在很多web系统上都会出现&#xff0c;一般我们当点击下载链接&#xff0c;便会向后台发送一个下载请求&#xff0c;一般这个请求会包含一个需要下载的文件名称&#xff0c;后台在收到请求后 会开始执行下载代码&#xff0c;将该文件名对应的文件…

Mysql数据库基础知识总复习

前言 小亭子正在努力的学习编程&#xff0c;接下来将开启javaEE的学习~~ 分享的文章都是学习的笔记和感悟&#xff0c;如有不妥之处希望大佬们批评指正~~ 同时如果本文对你有帮助的话&#xff0c;烦请点赞关注支持一波, 感激不尽~~ 目录 数据库基础知识 数据&#xff0c;数据…

GPT是什么,GPT-4是什么

GPT是Generative Pre-trained Transformer的缩写&#xff0c;是一种人工智能语言模型。为了实现自然语言生成和文本补全等功能&#xff0c;通过训练大规模数据集&#xff0c;GPT模型可以预测某个词或文本的下一个可能的词或文本。GPT是由OpenAI团队推出的&#xff0c;目前已经推…

如何用 GPT-4 帮你写游戏?

你知道的&#xff0c;GPT-4 发布了。 目前你想要用上 GPT-4&#xff0c;主要的渠道是 ChatGPT Plus 。作为交了订阅费的用户&#xff0c;你可以在对话的时候选择模型来使用。 另一种渠道&#xff0c;就是申请官方 API 的排队。我在申请 New Bing Chat 的时候&#xff0c;耐心被…

完成A轮融资,倍思如何发力场景化为品牌创造广阔未来?

凛冬过后的消费电子正在重新凝聚资本的目光。 近日&#xff0c;深圳市倍思科技有限公司宣布完成由深创投、中金资本联合领投&#xff0c;越秀产业基金、高榕资本跟投&#xff0c;金额数亿元人民币的A轮融资。 分析人士指出&#xff0c;消费电子的行业景气度在逐渐恢复&#x…