Go语言学习(二) 在线词典项目|青训营笔记

2023-10-22 00:40

本文主要是介绍Go语言学习(二) 在线词典项目|青训营笔记,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

Go 语言学习(二) 在线词典项目_青训营笔记

  • Go 语言学习(二) 在线词典项目_青训营笔记
    • 一、在线词典项目介绍
    • 二、开发步骤
      • 1. 抓包
      • 2. 代码生成
      • 3. 生成 request body
      • 4. 解析 request body
      • 5. 打印结果
    • 三、代码展示
      • 1. 主函数
      • 2. 彩云翻译函数
      • 3. 百度翻译函数

这是我参与「第三届青训营 -后端场」笔记创作活动的的第 2 篇笔记。

一、在线词典项目介绍

用户可以在命令行里面查询一个单词。此程序能通过调用第三方的 API 查询到单词的翻译并打印出来。

在这个项目里面,我学习了如何用 go 语言来发送 HTTP 请求、解析 json,学习了如何使用代码生成来提高开发效率。

在线词典介绍.png

二、开发步骤

1. 抓包

  • 要用到的 API 是彩云科技提供的在线翻译。先打开彩云翻译的网页,然后右键检查打开浏览器的开发者工具。

抓包1.png

  • 此时点击翻译按钮,浏览器会发送一系列请求,找到查询单词的请求。这是一个 HTTP 的 post 的请求,请求的 header 是一个 json,里面有两个字段,代表要翻译的语言和查询的单词。API 的返回结果里面会有 Wiki 和 dictionary 两个字段。需要用的结果主要在 dictionary.Explanations 字段里面,其他字段里面还包括音标等信息。

抓包2.png

抓包3.png

抓包4.png

2. 代码生成

  • 需要在 Golang 里面去发送这个请求。但是这个请求比较复杂,用代码构造很麻烦。可以用一种简单的方式来生成代码,右键浏览器里面的 copy as curl,在终端粘贴一下 curl 命令,可以返回一大串 json。

代码生成1.png

代码生成2.png

  • 打开代码生成网站,粘贴 curl 请求,即可自动生成 Golang 代码。

代码生成3.png

3. 生成 request body

  • 在 Golang 里面,需要生成一段 JSON ,常用的方式是先构造出来一个结构体,这个结构体和需要生成的 JSON 的结构是一一对应的。

生成 request body1.png

4. 解析 request body

  • 接下来把这个 response body 来解析出来。在 js/Python 这些脚本语言里面,body 是一个字典或者 map 的结构, 可以直接从里面取值,但是 golang 是个强类型语言,这种做法并不是最佳实践。更常用的方式是和 request 的一样,写一个结构体,把返回的 JSON 反序列化到结构体里面。但是在浏览器里面可以看到这个 API 返回的结构非常复杂,如果要一一定义结构体字段,非常繁琐并且容易出错。

解析 request body1.png

  • 此时可以使用对应的代码生成工具 ,把 json 字符串粘贴进去,自动生成对应结构体。

解析 request body2.png

5. 打印结果

  • 观察那个 json 可以看出需要的结果是在 Dictionary.explanations 里的,用 for range 循环来迭代它,然后直接打印结构,参照一些词典的显示方式,可以在前面打印出这个单词和它的音标。

打印结果.png

三、代码展示

经过课后编程实践,我实现了并行请求两个翻译引擎来提高响应速度。

下面是我的代码展示,包含了代码详细注释,便于理解。

1. 主函数

package mainimport ("fmt""os""sync""time"
)func main() { //此在线词典程序需要在 Git Bash终端命令行运行,如输入 go run *.go hellostart := time.Now()if len(os.Args) != 2 { // Args 保存命令行参数,以程序名称开头,这里第2个参数为要查询的单词fmt.Fprintf(os.Stderr, `usage: simpleDict WORD
example: simpleDict hello`) // Fprintf() 根据格式说明符格式化并写入 os.Stderr 。它返回写入的字节数和遇到的任何写入错误。os.Exit(1)}word := os.Args[1]wg := sync.WaitGroup{} // WaitGroup() 等待一组 goroutine 完成,主 goroutine 调用 Add() 来设置要等待的 goroutine 的数量,然后每个 goroutine 运行并在完成时调用Done(),同时, Wait()可以用来阻塞,直到所有的 goroutine 都完成wg.Add(2)              //将可能为负的增量添加到 WaitGroup() 计数器,如果计数器变为零,则所有在 Wait() 上阻塞的 goroutine 都会被释放,如果计数器变为负数,请添加错误处理go QueryCaiYun(word, &wg)go QueryBaiDu(word, &wg)wg.Wait()finish := time.Now()fmt.Println("runtime:", finish.Sub(start))
}

2. 彩云翻译函数

package mainimport ("bytes""encoding/json""fmt""io/ioutil""log""net/http""sync"
)type CaiYunDictRequest struct {TransType string `json:"trans_type"`Source    string `json:"source"`UserID    string `json:"user_id"`
}type CaiYunDictResponse struct {Rc   int `json:"rc"`Wiki struct {KnownInLaguages int `json:"known_in_laguages"`Description     struct {Source string      `json:"source"`Target interface{} `json:"target"`} `json:"description"`ID   string `json:"id"`Item struct {Source string `json:"source"`Target string `json:"target"`} `json:"item"`ImageURL  string `json:"image_url"`IsSubject string `json:"is_subject"`Sitelink  string `json:"sitelink"`} `json:"wiki"`Dictionary struct {Prons struct {EnUs string `json:"en-us"`En   string `json:"en"`} `json:"prons"`Explanations []string      `json:"explanations"`Synonym      []string      `json:"synonym"`Antonym      []string      `json:"antonym"`WqxExample   [][]string    `json:"wqx_example"`Entry        string        `json:"entry"`Type         string        `json:"type"`Related      []interface{} `json:"related"`Source       string        `json:"source"`} `json:"dictionary"`
}func QueryCaiYun(word string, wg *sync.WaitGroup) {client := &http.Client{} //定义客户// var data = strings.NewReader(`{"trans_type":"en2zh","source":"good"}`) //把输入的字符串 data 转换成流 reqrequest := CaiYunDictRequest{TransType: "en2zh", Source: word}buf, err := json.Marshal(request) // Marshal() 返回 request 的 JSON 编码,序列化为一个 byte 数组。if err != nil {log.Fatal(err) //打印日志,退出程序}var data = bytes.NewReader(buf) //把输入的 byte 数组转换成流 req/* 创建请求 */req, err := http.NewRequest("POST", "https://api.interpreter.caiyunai.com/v1/dict", data)if err != nil {log.Fatal(err) //打印日志,退出程序}/* 设置请求头 */req.Header.Set("Accept", "application/json, text/plain, */*")req.Header.Set("Accept-Language", "zh-CN,zh;q=0.9,en;q=0.8,en-GB;q=0.7,en-US;q=0.6")req.Header.Set("Connection", "keep-alive")req.Header.Set("Content-Type", "application/json;charset=UTF-8")req.Header.Set("Origin", "https://fanyi.caiyunapp.com")req.Header.Set("Referer", "https://fanyi.caiyunapp.com/")req.Header.Set("Sec-Fetch-Dest", "empty")req.Header.Set("Sec-Fetch-Mode", "cors")req.Header.Set("Sec-Fetch-Site", "cross-site")req.Header.Set("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/100.0.4896.127 Safari/537.36 Edg/100.0.1185.44")req.Header.Set("X-Authorization", "token:qgemv4jr1y38jyq6vhvi")req.Header.Set("app-name", "xy")req.Header.Set("os-type", "web")req.Header.Set("sec-ch-ua", `" Not A;Brand";v="99", "Chromium";v="100", "Microsoft Edge";v="100"`)req.Header.Set("sec-ch-ua-mobile", "?0")req.Header.Set("sec-ch-ua-platform", `"Windows"`)/* 发起请求 */resp, err := client.Do(req)if err != nil {log.Fatal(err) //打印日志,退出程序}defer resp.Body.Close() //defer 会在函数结束后从后往前触发,Close() 手动关闭 Body流,防止内存资源泄露/*读取响应*/bodyText, err := ioutil.ReadAll(resp.Body)if err != nil {log.Fatal(err) //打印日志,退出程序}if resp.StatusCode != 200 { // 防御式编程,判断状态码是否正确log.Fatal("bad StatusCode:", resp.StatusCode, "body", string(bodyText)) //打印日志,退出程序}// fmt.Printf("%s\n", bodyText)var dictResponse CaiYunDictResponseerr = json.Unmarshal(bodyText, &dictResponse) //Unmarshal()解析 bodyText的 JSON 编码的数据并反序列化将结果存储在 dictResponse 指向的值中。if err != nil {log.Fatal(err) //打印日志,退出程序}// fmt.Printf("%#v\n", dictResponse)fmt.Println("--------------------彩云翻译-----------------------")fmt.Println(word, "UK:", dictResponse.Dictionary.Prons.En, "US:", dictResponse.Dictionary.Prons.EnUs)for _, item := range dictResponse.Dictionary.Explanations {fmt.Println(item)}wg.Done()
}

3. 百度翻译函数

package mainimport ("bytes""encoding/json""fmt""io/ioutil""log""net/http""sync"
)type BaiDuDictRequest struct {Query  string `json:"query"`UserID string `json:"user_id"`
}type BaiDuDictResponse struct {TransResult struct {Data []struct {Dst        string          `json:"dst"`PrefixWrap int             `json:"prefixWrap"`Result     [][]interface{} `json:"result"`Src        string          `json:"src"`} `json:"data"`From     string `json:"from"`Status   int    `json:"status"`To       string `json:"to"`Type     int    `json:"type"`Phonetic []struct {SrcStr string `json:"src_str"`TrgStr string `json:"trg_str"`} `json:"phonetic"`} `json:"trans_result"`DictResult struct {Edict struct {Item []struct {TrGroup []struct {Tr          []string      `json:"tr"`Example     []interface{} `json:"example"`SimilarWord []string      `json:"similar_word"`} `json:"tr_group"`Pos string `json:"pos"`} `json:"item"`Word string `json:"word"`} `json:"edict"`Collins struct {Entry []struct {EntryID string `json:"entry_id"`Type    string `json:"type"`Value   []struct {MeanType []struct {InfoType string `json:"info_type"`InfoID   string `json:"info_id"`Example  []struct {ExampleID string `json:"example_id"`TtsSize   string `json:"tts_size"`Tran      string `json:"tran"`Ex        string `json:"ex"`TtsMp3    string `json:"tts_mp3"`} `json:"example"`} `json:"mean_type"`Gramarinfo []interface{} `json:"gramarinfo"`Tran       string        `json:"tran"`Def        string        `json:"def"`MeanID     string        `json:"mean_id"`Posp       []struct {Label string `json:"label"`} `json:"posp"`} `json:"value"`} `json:"entry"`WordName      string `json:"word_name"`Frequence     string `json:"frequence"`WordEmphasize string `json:"word_emphasize"`WordID        string `json:"word_id"`} `json:"collins"`From        string `json:"from"`SimpleMeans struct {WordName  string   `json:"word_name"`From      string   `json:"from"`WordMeans []string `json:"word_means"`Exchange  struct {WordPl  []string `json:"word_pl"`WordEst []string `json:"word_est"`WordEr  []string `json:"word_er"`} `json:"exchange"`Tags struct {Core  []string `json:"core"`Other []string `json:"other"`} `json:"tags"`Symbols []struct {PhEn  string `json:"ph_en"`PhAm  string `json:"ph_am"`Parts []struct {Part  string   `json:"part"`Means []string `json:"means"`} `json:"parts"`PhOther string `json:"ph_other"`} `json:"symbols"`} `json:"simple_means"`Lang   string `json:"lang"`Oxford struct {Entry []struct {Tag  string `json:"tag"`Name string `json:"name"`Data []struct {Tag  string `json:"tag"`Data []struct {Tag   string `json:"tag"`P     string `json:"p"`PText string `json:"p_text"`} `json:"data"`} `json:"data"`} `json:"entry"`Unbox []struct {Tag  string `json:"tag"`Type string `json:"type"`Name string `json:"name"`Data []struct {Tag     string   `json:"tag"`Text    string   `json:"text,omitempty"`Words   []string `json:"words,omitempty"`Outdent string   `json:"outdent,omitempty"`Data    []struct {Tag    string `json:"tag"`EnText string `json:"enText"`ChText string `json:"chText"`} `json:"data,omitempty"`} `json:"data"`} `json:"unbox"`} `json:"oxford"`Sanyms []struct {Tit  string `json:"tit"`Type string `json:"type"`Data []struct {P string   `json:"p"`D []string `json:"d"`} `json:"data"`} `json:"sanyms"`Usecase struct {Idiom []struct {P    string `json:"p"`Tag  string `json:"tag"`Data []struct {Tag  string `json:"tag"`Data []struct {EnText string `json:"enText"`Tag    string `json:"tag"`ChText string `json:"chText"`Before []struct {Tag  string `json:"tag"`Data []struct {EnText string `json:"enText"`Tag    string `json:"tag"`ChText string `json:"chText"`} `json:"data"`} `json:"before,omitempty"`} `json:"data"`} `json:"data"`} `json:"idiom"`} `json:"usecase"`BaiduPhrase []struct {Tit   []string `json:"tit"`Trans []string `json:"trans"`} `json:"baidu_phrase"`QueryExplainVideo struct {ID           int    `json:"id"`UserID       string `json:"user_id"`UserName     string `json:"user_name"`UserPic      string `json:"user_pic"`Query        string `json:"query"`Direction    string `json:"direction"`Type         string `json:"type"`Tag          string `json:"tag"`Detail       string `json:"detail"`Status       string `json:"status"`SearchType   string `json:"search_type"`FeedURL      string `json:"feed_url"`Likes        string `json:"likes"`Plays        string `json:"plays"`CreatedAt    string `json:"created_at"`UpdatedAt    string `json:"updated_at"`DuplicateID  string `json:"duplicate_id"`RejectReason string `json:"reject_reason"`CoverURL     string `json:"coverUrl"`VideoURL     string `json:"videoUrl"`ThumbURL     string `json:"thumbUrl"`VideoTime    string `json:"videoTime"`VideoType    string `json:"videoType"`} `json:"queryExplainVideo"`} `json:"dict_result"`LijuResult struct {Double string   `json:"double"`Tag    []string `json:"tag"`Single string   `json:"single"`} `json:"liju_result"`Logid int64 `json:"logid"`
}func QueryBaiDu(word string, wg *sync.WaitGroup) {client := &http.Client{} //定义客户// var data = strings.NewReader(`query=good`) //把输入的字符串 data 转换成流 reqrequest := BaiDuDictRequest{Query: word}buf, err := json.Marshal(request) // Marshal() 返回 request 的 JSON 编码,序列化为一个 byte 数组。if err != nil {log.Fatal(err) //打印日志,退出程序}var data = bytes.NewReader(buf) //把输入的 byte 数组转换成流 req/* 创建请求 */req, err := http.NewRequest("POST", "https://fanyi.baidu.com/langdetect", data)if err != nil {log.Fatal(err) //打印日志,退出程序}/* 设置请求头 */req.Header.Set("Accept", "*/*")req.Header.Set("Accept-Language", "zh-CN,zh;q=0.9,en;q=0.8,en-GB;q=0.7,en-US;q=0.6")req.Header.Set("Connection", "keep-alive")req.Header.Set("Content-Type", "application/x-www-form-urlencoded; charset=UTF-8")req.Header.Set("Cookie", `BIDUPSID=2860D678CCB10886990D4D819CC24BAB; PSTM=1603262095; REALTIME_TRANS_SWITCH=1; FANYI_WORD_SWITCH=1; HISTORY_SWITCH=1; SOUND_SPD_SWITCH=1; SOUND_PREFER_SWITCH=1; __yjs_duid=1_3242d9ae5ec151bc4e7e9d908fe0e54c1620968286434; BDUSS=g3Tm93dWtraHZkRUdsdzlJeDEyalp2RmpZOW1RNmlDMUV3d2N0M0c4Z0pqNXhoRVFBQUFBJCQAAAAAAAAAAAEAAABffmtXxKnTsNChutpYSAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAkCdWEJAnVhfk; BDUSS_BFESS=g3Tm93dWtraHZkRUdsdzlJeDEyalp2RmpZOW1RNmlDMUV3d2N0M0c4Z0pqNXhoRVFBQUFBJCQAAAAAAAAAAAEAAABffmtXxKnTsNChutpYSAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAkCdWEJAnVhfk; APPGUIDE_10_0_2=1; BAIDUID=3A21E0D3A023E0BF48D5E6AB59882FC3:SL=0:NR=20:FG=1; MAWEBCUID=web_ZbMGPxbtNTJgOhwuypnUUKjyVeChjrWNsCSTdnAIkJyWEtWEYb; BDORZ=FFFB88E999055A3F8A630C64834BD6D0; Hm_lvt_64ecd82404c51e03dc91cb9e8c025574=1652153403,1652175540,1652186130,1652278875; Hm_lpvt_64ecd82404c51e03dc91cb9e8c025574=1652506784; delPer=0; PSINO=1; BAIDUID_BFESS=3A21E0D3A023E0BF48D5E6AB59882FC3:SL=0:NR=20:FG=1; RT="z=1&dm=baidu.com&si=hqolag82j09&ss=l35hyf6s&sl=2&tt=56c&bcn=https%3A%2F%2Ffclog.baidu.com%2Flog%2Fweirwood%3Ftype%3Dperf&ld=5ne&ul=2axq&hd=2b02"; BA_HECTOR=24052g04012lag8kt41h7ulf10q; BDRCVFR[OEHfjv-pq1f]=mk3SLVN4HKm; BDRCVFR[dG2JNJb_ajR]=mk3SLVN4HKm; BDRCVFR[-pGxjrCMryR]=mk3SLVN4HKm; H_PS_PSSID=`)req.Header.Set("Origin", "https://fanyi.baidu.com")req.Header.Set("Referer", "https://fanyi.baidu.com/?aldtype=16047")req.Header.Set("Sec-Fetch-Dest", "empty")req.Header.Set("Sec-Fetch-Mode", "cors")req.Header.Set("Sec-Fetch-Site", "same-origin")req.Header.Set("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/100.0.4896.127 Safari/537.36 Edg/100.0.1185.44")req.Header.Set("X-Requested-With", "XMLHttpRequest")req.Header.Set("sec-ch-ua", `" Not A;Brand";v="99", "Chromium";v="100", "Microsoft Edge";v="100"`)req.Header.Set("sec-ch-ua-mobile", "?0")req.Header.Set("sec-ch-ua-platform", `"Windows"`)/* 发起请求 */resp, err := client.Do(req)if err != nil {log.Fatal(err) //打印日志,退出程序}defer resp.Body.Close() //defer 会在函数结束后从后往前触发,Close() 手动关闭 Body流,防止内存资源泄露/*读取响应*/bodyText, err := ioutil.ReadAll(resp.Body)if err != nil {log.Fatal(err) //打印日志,退出程序}if resp.StatusCode != 200 { // 防御式编程,判断状态码是否正确log.Fatal("bad StatusCode:", resp.StatusCode, "body", string(bodyText)) //打印日志,退出程序}// fmt.Printf("%s\n", bodyText)var dictResponse BaiDuDictResponseerr = json.Unmarshal(bodyText, &dictResponse) //Unmarshal()解析 bodyText的 JSON 编码的数据并反序列化将结果存储在 dictResponse 指向的值中。if err != nil {log.Fatal(err) //打印日志,退出程序}// fmt.Printf("%#v\n", dictResponse)fmt.Println("--------------------百度翻译-----------------------")fmt.Println(word, "UK:", dictResponse.DictResult.SimpleMeans.Symbols, "US:", dictResponse.DictResult.SimpleMeans.Symbols)for _, item := range dictResponse.DictResult.SimpleMeans.WordMeans {fmt.Println(item)}wg.Done()
}

这篇关于Go语言学习(二) 在线词典项目|青训营笔记的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!


原文地址:https://blog.csdn.net/qq_40734758/article/details/128180214
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.chinasem.cn/article/257968

相关文章

go中的时间处理过程

《go中的时间处理过程》:本文主要介绍go中的时间处理过程,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录1 获取当前时间2 获取当前时间戳3 获取当前时间的字符串格式4 相互转化4.1 时间戳转时间字符串 (int64 > string)4.2 时间字符串转时间

Go语言中make和new的区别及说明

《Go语言中make和new的区别及说明》:本文主要介绍Go语言中make和new的区别及说明,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录1 概述2 new 函数2.1 功能2.2 语法2.3 初始化案例3 make 函数3.1 功能3.2 语法3.3 初始化

深度解析Java项目中包和包之间的联系

《深度解析Java项目中包和包之间的联系》文章浏览阅读850次,点赞13次,收藏8次。本文详细介绍了Java分层架构中的几个关键包:DTO、Controller、Service和Mapper。_jav... 目录前言一、各大包1.DTO1.1、DTO的核心用途1.2. DTO与实体类(Entity)的区别1

Go语言中nil判断的注意事项(最新推荐)

《Go语言中nil判断的注意事项(最新推荐)》本文给大家介绍Go语言中nil判断的注意事项,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友参考下吧... 目录1.接口变量的特殊行为2.nil的合法类型3.nil值的实用行为4.自定义类型与nil5.反射判断nil6.函数返回的

Go语言数据库编程GORM 的基本使用详解

《Go语言数据库编程GORM的基本使用详解》GORM是Go语言流行的ORM框架,封装database/sql,支持自动迁移、关联、事务等,提供CRUD、条件查询、钩子函数、日志等功能,简化数据库操作... 目录一、安装与初始化1. 安装 GORM 及数据库驱动2. 建立数据库连接二、定义模型结构体三、自动迁

如何在Spring Boot项目中集成MQTT协议

《如何在SpringBoot项目中集成MQTT协议》本文介绍在SpringBoot中集成MQTT的步骤,包括安装Broker、添加EclipsePaho依赖、配置连接参数、实现消息发布订阅、测试接口... 目录1. 准备工作2. 引入依赖3. 配置MQTT连接4. 创建MQTT配置类5. 实现消息发布与订阅

springboot项目打jar制作成镜像并指定配置文件位置方式

《springboot项目打jar制作成镜像并指定配置文件位置方式》:本文主要介绍springboot项目打jar制作成镜像并指定配置文件位置方式,具有很好的参考价值,希望对大家有所帮助,如有错误... 目录一、上传jar到服务器二、编写dockerfile三、新建对应配置文件所存放的数据卷目录四、将配置文

Go语言代码格式化的技巧分享

《Go语言代码格式化的技巧分享》在Go语言的开发过程中,代码格式化是一个看似细微却至关重要的环节,良好的代码格式化不仅能提升代码的可读性,还能促进团队协作,减少因代码风格差异引发的问题,Go在代码格式... 目录一、Go 语言代码格式化的重要性二、Go 语言代码格式化工具:gofmt 与 go fmt(一)

怎么用idea创建一个SpringBoot项目

《怎么用idea创建一个SpringBoot项目》本文介绍了在IDEA中创建SpringBoot项目的步骤,包括环境准备(JDK1.8+、Maven3.2.5+)、使用SpringInitializr... 目录如何在idea中创建一个SpringBoot项目环境准备1.1打开IDEA,点击New新建一个项

springboot项目中整合高德地图的实践

《springboot项目中整合高德地图的实践》:本文主要介绍springboot项目中整合高德地图的实践,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录一:高德开放平台的使用二:创建数据库(我是用的是mysql)三:Springboot所需的依赖(根据你的需求再