长安链使用Golang编写智能合约教程(三)

本篇主要介绍长安链Go SDK写智能合约的一些常见方法的使用方法或介绍

资料来源:

  1. 官方文档
  2. 官方示例合约库
  3. 官方SDK接口文档

一、获取参数、获取状态、获取历史记录的方法解析

注意!

这些查询链上数据的方法:只能是查询本合约之前上链的数据,别的合约上链的数据就算key相同你也是不能查的,其他查询方法也一样

        // GetArgs get arg from transaction parameters// @return: 参数map
	GetArgs() map[string][]byte
(常用,获取参数的方法,之前的示例基本上都用到)

	// GetState get [key, field] from chain// @param key: 获取的参数名// @param field: 获取的参数名// @return1: 获取结果,格式为string// @return2: 获取错误信息
	// Deprecated: 无法通过返回值来判断state是否存在,建议使用GetStateWithExists
	GetState(key, field string) (string, error)

(通过空间域名+key 查询值)官方说废弃了建议用GetStateWithExists 


	// GetStateWithExists get [key, field] from chain// @param key: 获取的参数名// @param field: 获取的参数名// @return1: 获取结果,格式为string// @return2: 是否存在,bool, 字符串长度为0不代表不存在// @return3: 获取错误信息GetStateWithExists(key, field string) (string, bool, error)

(通过空间域名+key 查询值) 返回值,是否存在,错误参数

        其中如果不存在返回空和false


	// GetBatchState get [BatchKeys] from chain// @param batchKey: 获取的参数名// @return1: 获取结果// @return2: 获取错误信息GetBatchState(batchKeys []*vmPb.BatchKey) ([]*vmPb.BatchKey, error)

没看懂怎么用,像是批量查询,但是BatchKey很多参数


	// GetStateByte get [key, field] from chain// @param key: 获取的参数名// @param field: 获取的参数名// @return1: 获取结果,格式为[]byte, nil表示不存在// @return2: 获取错误信息GetStateByte(key, field string) ([]byte, error)

(通过空间域名+key 查询值) 返回值[]byte,错误参数


	// GetStateFromKey get [key] from chain// @param key: 获取的参数名// @return1: 获取结果,格式为string// @return2: 获取错误信息
// Deprecated: 无法通过返回值来判断state是否存在,建议使用GetStateFromKeyWithExistsGetStateFromKey(key string) (string, error)

注意!

       通过key去查值,如果前面你存值是用  field 、key 两个参数存的,那么你用一个key值是取不到任何值的


	// GetStateFromKeyWithExists get [key] from chain// @param key: 获取的参数名// @return1: 获取结果,格式为string// @return2: 是否存在,bool, 字符串长度为0不代表不存在// @return3: 获取错误信息GetStateFromKeyWithExists(key string) (string, bool, error)

同上


	// GetStateFromKeyByte get [key] from chain// @param key: 获取的参数名// @return1: 获取结果,格式为[]byte, nil表示不存在// @return2: 获取错误信息GetStateFromKeyByte(key string) ([]byte, error)

同上


 

二、存数据、删除数据的一些方法

        // PutState put [key, field, value] to chain// @param1 key: 参数名// @param1 field: 参数名// @param2 value: 参数值,类型为string// @return1: 上传参数错误信息PutState(key, field string, value string) error

存数据方法:  参数依次是 key值、空间域名、要存的数据 (string)

官方的一些示例是:空间域名、 key值、要存的数据  (string)


	// PutStateByte put [key, field, value] to chain// @param1 key: 参数名// @param1 field: 参数名// @param2 value: 参数值,类型为[]byte// @return1: 上传参数错误信息PutStateByte(key, field string, value []byte) error

存数据方法:  参数依次是 key值、空间域名、要存的数据  []byte

官方的一些示例是:空间域名、 key值、要存的数据  []byte


	// PutStateFromKey put [key, value] to chain// @param1 key: 参数名// @param2 value: 参数值,类型为string// @return1: 上传参数错误信息
	PutStateFromKey(key string, value string) error

存数据方法:  参数依次是 key值、要存的数据 string

注意 ,不带空间域名去存,取值的时候也要不带空间域名


	// PutStateFromKeyByte put [key, value] to chain// @param1 key: 参数名// @param2 value: 参数值,类型为[]byte// @return1: 上传参数错误信息
	PutStateFromKeyByte(key string, value []byte) error

存数据方法:  参数依次是 key值、要存的数据 []byte


	// DelState delete [key, field] to chain// @param1 key: 删除的参数名// @param1 field: 删除的参数名// @return1:删除参数的错误信息
	DelState(key, field string) error

删除数据方法:  参数依次是 key值、空间域名

注意:删除不是真的删除数据,会新增一条交易,交易内容是 key 、field 的字段isdelete变成 true    ,  并且如果区块链上没有 key、field的数据同样也能删除、也会新增一条数据


	// DelStateFromKey delete [key] to chain// @param1 key: 删除的参数名// @return1:删除参数的错误信息
	DelStateFromKey(key string) error

删除数据的方法通过key

三、获取其他值的一些方法

        // GetCreatorOrgId get tx creator org id// @return1: 合约创建者的组织ID// @return2: 获取错误信息GetCreatorOrgId() (string, error)

获取合约创建者的组织ID


	// GetCreatorRole get tx creator role// @return1: 合约创建者的角色// @return2: 获取错误信息GetCreatorRole() (string, error)

获取合约创建者的角色


	// GetCreatorPk get tx creator pk// @return1: 合约创建者的公钥// @return2: 获取错误信息GetCreatorPk() (string, error)

获取合约创建者的公钥

在IDE可以获取,在使用证书+私钥的链,还没测过


	// GetSenderOrgId get tx sender org id// @return1: 交易发起者的组织ID// @return2: 获取错误信息
	GetSenderOrgId() (string, error)

获取交易发起者的组织ID

	// GetSenderRole get tx sender role// @return1: 交易发起者的角色// @return2: 获取错误信息GetSenderRole() (string, error)

获取交易发起者的角色


	// GetSenderPk get tx sender pk// @return1: 交易发起者的公钥// @return2: 获取错误信息GetSenderPk() (string, error)

获取 交易发起者的公钥


	// GetBlockHeight get tx block height// @return1: 当前块高度// @return2: 获取错误信息GetBlockHeight() (int, error)

获取当前块高度


	// GetTxId get current tx id// @return1: 交易ID// @return2: 获取错误信息GetTxId() (string, error)

获取 交易ID


	// GetTxInfo get tx info// @param txId :合约交易IDGetTxInfo(txId string) protogo.Response

获取合约交易ID


	// GetTxTimeStamp get tx timestamp// @return1: 交易timestamp// @return2: 获取错误信息GetTxTimeStamp() (string, error)

获取交易timestamp


	// EmitEvent emit event, you can subscribe to the event using the SDK// @param1 topic: 合约事件的主题// @param2 data: 合约事件的数据,参数数量不可大于16EmitEvent(topic string, data []string)

发布合约事件,发布了的化,主题和参数,会被订阅者收到


	// Log record log to chain server// @param message: 事情日志的信息//DeprecatedLog(message string)

日记记录,会写进节点日志


	// Debugf record log to chain server// @param format: 日志格式化模板// @param a: 模板参数Debugf(format string, a ...interface{})

同上


	// Infof record log to chain server// @param format: 日志格式化模板// @param a: 模板参数Infof(format string, a ...interface{})

同上


	// Warnf record log to chain server// @param format: 日志格式化模板// @param a: 模板参数Warnf(format string, a ...interface{})

同上


	// Errorf record log to chain server// @param format: 日志格式化模板// @param a: 模板参数Errorf(format string, a ...interface{})

同上


	// CallContract invoke another contract and get response// @param1: 合约名称// @param2: 合约方法// @param3: 合约合约参数// @return1: 合约结果
CallContract(contractName, method string, args map[string][]byte) protogo.Response

合约里面调用别的合约?不知道是干嘛的

官方解释:跨合约调用,用于调用已经安装的其他合约的

四、获取历史数据的一些方法

// NewIterator range of [startKey, limitKey), front closed back open// @param1: 范围查询起始key// @param2: 范围查询结束key// @return1: 根据起始key生成的迭代器// @return2: 获取错误信息NewIterator(startKey string, limitKey string) (ResultSetKV, error)

不清出这个起始key、结束key是什么意思,如果key是一些字母也有起始和结束吗?

难以理解,懂得朋友辛苦留言指导一下


	// NewIteratorWithField range of [key+"#"+startField, key+"#"+limitField), front closed back open// @param1: 分别与param2, param3 构成查询起始和结束的key// @param2: [param1 + "#" + param2] 来获取查询起始的key// @param3: [param1 + "#" + param3] 来获取查询结束的key// @return1: 根据起始位置生成的迭代器// @return2: 获取错误信息
NewIteratorWithField(key string, startField string, limitField string) (ResultSetKV, error)

同上


	// NewIteratorPrefixWithKeyField range of [key+"#"+field, key+"#"+field], front closed back closed// @param1: [ param1 + "#" +param2 ] 构成前缀范围查询的key// @param2: [ param1 + "#" +param2 ] 构成前缀范围查询的key// @return1: 根据起始位置生成的迭代器// @return2: 获取错误信息NewIteratorPrefixWithKeyField(key string, field string) (ResultSetKV, error)

同上


	// NewIteratorPrefixWithKey range of [key, key], front closed back closed// @param1: 前缀范围查询起始key// @return1: 根据起始位置生成的迭代器// @return2: 获取错误信息NewIteratorPrefixWithKey(key string) (ResultSetKV, error)

 查询key相同的所有数据,使用方法可以参考教程二

只能是查询本合约之前上链的数据,别的合约上链的数据就算key相同你也是不能查的,其他查询方法也一样


	// NewHistoryKvIterForKey query all historical data of key, field// @param1: 查询历史的key// @param2: 查询历史的field// @return1: 根据key, field 生成的历史迭代器// @return2: 获取错误信息
	NewHistoryKvIterForKey(key, field string) (KeyHistoryKvIter, error)

查询 field 、key相同的所有数据,使用方法可以参考教程二

只能是查询本合约之前上链的数据,别的合约上链的数据就算key相同你也是不能查的,其他查询方法也一样


	// GetSenderAddr Get the address of the origin caller address, same with Origin()// @return1: origin caller address// @return2: 获取错误信息// DeprecatedGetSenderAddr() (string, error)

被弃用了,别学


	// Sender Get the address of the sender address, if the contract is called by another contract, the result will be// the caller contract's address.// Sender will return system contract address when executing the init or upgrade method (If you need to return the// user address, we recommend using Origin method here), because the init and upgrade methods are cross-contract// txs (system contract -> common contract).// @return1: sender address// @return2: 获取错误信息Sender() (string, error)

获取发送者的地址。如果合约是由另一个合约调用的,结果将是调用者合约的地址。


	// Origin Get the address of the tx origin caller address// @return1: origin caller address// @return2: 获取错误信息Origin() (string, error)

获取交易原始调用者的地址

 五、示例合约

以下合约是我在写这个教程测试用的,只写了部分接口测试

/*
Copyright (C) BABEC. All rights reserved.
Copyright (C) THL A29 Limited, a Tencent company. All rights reserved.SPDX-License-Identifier: Apache-2.0
*/package mainimport ("chainmaker/pb/protogo""chainmaker/sandbox""chainmaker/sdk""encoding/json""fmt""log""strconv"
)type FactContract struct {
}// 存证对象
type Fact struct {FileHash stringFileName stringTime     int
}// 新建存证对象
func NewFact(fileHash string, fileName string, time int) *Fact {fact := &Fact{FileHash: fileHash,FileName: fileName,Time:     time,}return fact
}func (f *FactContract) InitContract() protogo.Response {return sdk.Success([]byte("Init contract success"))
}func (f *FactContract) UpgradeContract() protogo.Response {return sdk.Success([]byte("Upgrade contract success"))
}func (f *FactContract) InvokeContract(method string) protogo.Response {switch method {case "save":return f.Save()case "findByFileHash":return f.FindByFileHash()case "deltedByFileHash":return f.DeleteByFileHash()case "getHistoryByFileHash":return f.GetHistoryByFileHash()case "getStateFromKey":return f.GetStateFromKey()case "getStateByte":return f.GetStateByte()case "getStateWithExists":return f.GetStateWithExists()case "getCreatorOrgId":return f.GetCreatorOrgId()case "getCreatorPk":return f.GetCreatorPk()case "GetSenderOrgId":return f.GetSenderOrgId()case "GetSenderRole":return f.GetSenderRole()case "GetSenderPk":return f.GetSenderPk()case "GetBlockHeight":return f.GetBlockHeight()case "GetTxId":return f.GetTxId()case "GetTxTimeStamp":return f.GetTxTimeStamp()default:return sdk.Error("invalid method")}
}func (f *FactContract) Save() protogo.Response {params := sdk.Instance.GetArgs()// 获取参数fileHash := string(params["file_hash"])fileName := string(params["file_name"])timeStr := string(params["time"])time, err := strconv.Atoi(timeStr)if err != nil {msg := "time is [" + timeStr + "] not int"sdk.Instance.Errorf(msg)return sdk.Error(msg)}// 构建结构体fact := NewFact(fileHash, fileName, time)// 序列化factBytes, err := json.Marshal(fact)if err != nil {return sdk.Error(fmt.Sprintf("传过来的参数序列化失败, err: %s", err))}// 发送事件sdk.Instance.EmitEvent("topic_vx", []string{fact.FileHash, fact.FileName})// 存储数据err = sdk.Instance.PutStateByte("fact_bytes", fact.FileHash, factBytes)if err != nil {return sdk.Error("fail to save fact bytes")}// 记录日志// sdk.Instance.Infof("[save] fileHash=" + fact.FileHash)// sdk.Instance.Infof("[save] fileName=" + fact.FileName)createUser, _ := sdk.Instance.GetSenderRole()sdk.Instance.Infof("[saveUser] create=" + createUser)// 返回结果return sdk.Success([]byte(fact.FileName + fact.FileHash))}func (f *FactContract) FindByFileHash() protogo.Response {// 获取参数fileHash := string(sdk.Instance.GetArgs()["file_hash"])// 查询结果result, err := sdk.Instance.GetStateByte("fact_bytes", fileHash)if err != nil {return sdk.Error("failed to call get_state")}// 反序列化var fact Factif err = json.Unmarshal(result, &fact); err != nil {return sdk.Error(fmt.Sprintf("unmarshal fact failed, err: %s", err))}// 记录日志sdk.Instance.Infof("[find_by_file_hash] fileHash=" + fact.FileHash)sdk.Instance.Infof("[find_by_file_hash] fileName=" + fact.FileName)// 返回结果return sdk.Success(result)
}func (f *FactContract) DeleteByFileHash() protogo.Response {// 获取参数fileHash := string(sdk.Instance.GetArgs()["file_hash"])// 查询结果err := sdk.Instance.DelState("fact_bytes", fileHash)if err != nil {return sdk.Error("failed to delere get_state")}// 返回结果return sdk.Success(nil)
}func (f *FactContract) GetHistoryByFileHash() protogo.Response {// 获取参数fileHash := string(sdk.Instance.GetArgs()["file_hash"])// 查询结果iter, err := sdk.Instance.NewHistoryKvIterForKey("fact_bytes", fileHash)if err != nil {return sdk.Error("failed to delere get_state")}defer iter.Close()var keyModifications []*sdk.KeyModification// 遍历结果for {if !iter.HasNext() {break}keyModification, err := iter.Next()if err != nil {sdk.Instance.Infof("Error iterating: %v", err)}if keyModification == nil {break}keyModifications = append(keyModifications, keyModification)sdk.Instance.Infof("Key: %s, Field: %s, Value: %s, TxId: %s, BlockHeight: %d, IsDelete: %t, Timestamp: %s, \n",keyModification.Key, keyModification.Field, keyModification.Value, keyModification.TxId, keyModification.BlockHeight, keyModification.IsDelete, keyModification.Timestamp)}jsonBytes, err := json.Marshal(keyModifications)if err != nil {return sdk.Error(fmt.Sprintf("Error marshaling keyModifications: %v", err))}// 返回结果return sdk.Success(jsonBytes)
}func (f *FactContract) GetStateFromKey() protogo.Response {// 获取参数fileHash := string(sdk.Instance.GetArgs()["file_hash"])// 查询结果result, err := sdk.Instance.GetStateFromKey(fileHash)if err != nil {return sdk.Error("failed to call get_state")}sdk.Instance.Infof("[GetStateFromKey] result=" + result)byteSlice := []byte(result)// 返回结果return sdk.Success(byteSlice)
}func (f *FactContract) GetStateByte() protogo.Response {// 获取参数fileHash := string(sdk.Instance.GetArgs()["file_hash"])// 查询结果result, err := sdk.Instance.GetStateByte("fact_bytes", fileHash)if err != nil {return sdk.Error("failed to call get_state")}sdk.Instance.Infof("[GetStateByte] result=" + string(result))// 返回结果return sdk.Success(result)
}func (f *FactContract) GetStateWithExists() protogo.Response {// 获取参数fileHash := string(sdk.Instance.GetArgs()["file_hash"])// 查询结果result, exit, err := sdk.Instance.GetStateWithExists("fact_bytes", fileHash)if err != nil {return sdk.Error("failed to call get_state")}exitStr := fmt.Sprintf("%v", exit)sdk.Instance.Infof("[GetStateByte] result=" + result + "bool:" + string(exitStr))// 返回结果return sdk.Success([]byte(result))
}func (f *FactContract) GetCreatorOrgId() protogo.Response {// 查询结果result, err := sdk.Instance.GetCreatorOrgId()if err != nil {return sdk.Error("failed to call get_state")}sdk.Instance.Infof("[GetCreatorOrgId] GetCreatorOrgId=" + result)// 返回结果return sdk.Success([]byte(result))
}func (f *FactContract) GetCreatorPk() protogo.Response {// 查询结果result, err := sdk.Instance.GetCreatorPk()if err != nil {return sdk.Error("failed to call get_state")}sdk.Instance.Infof("[GetCreatorPk] GetCreatorPk=" + result)// 返回结果return sdk.Success([]byte(result))
}func (f *FactContract) GetSenderOrgId() protogo.Response {// 查询结果result, err := sdk.Instance.GetSenderOrgId()if err != nil {return sdk.Error("failed to call get_state")}sdk.Instance.Infof("[GetSenderOrgId] GetSenderOrgId=" + result)// 返回结果return sdk.Success([]byte(result))
}func (f *FactContract) GetSenderRole() protogo.Response {// 查询结果result, err := sdk.Instance.GetSenderRole()if err != nil {return sdk.Error("failed to call get_state")}sdk.Instance.Infof("[GetSenderRole] GetSenderRole=" + result)// 返回结果return sdk.Success([]byte(result))
}func (f *FactContract) GetSenderPk() protogo.Response {// 查询结果result, err := sdk.Instance.GetSenderPk()if err != nil {return sdk.Error("failed to call get_state")}sdk.Instance.Infof("[GetSenderPk] GetSenderPk=" + result)// 返回结果return sdk.Success([]byte(result))
}
func (f *FactContract) GetBlockHeight() protogo.Response {// 查询结果result, err := sdk.Instance.GetBlockHeight()if err != nil {return sdk.Error("failed to call get_state")}str := strconv.Itoa(result) // 将int转换为字符串bytes := []byte(str)        // 将字符串转换为[]byte// 返回结果return sdk.Success(bytes)
}func (f *FactContract) GetTxId() protogo.Response {// 查询结果result, err := sdk.Instance.GetTxId()if err != nil {return sdk.Error("failed to call get_state")}sdk.Instance.Infof("[GetTxId] GetTxId=" + result)// 返回结果return sdk.Success([]byte(result))
}func (f *FactContract) GetTxTimeStamp() protogo.Response {// 查询结果result, err := sdk.Instance.GetTxTimeStamp()if err != nil {return sdk.Error("failed to call get_state")}sdk.Instance.Infof("[GetTxTimeStamp] GetTxTimeStamp=" + result)// 返回结果return sdk.Success([]byte(result))
}func main() {err := sandbox.Start(new(FactContract))if err != nil {log.Fatal(err)}
}

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

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

相关文章

信息学一周赛事安排

本周比赛提醒 本周有以下几场比赛即将开始: 1.ABC-356 比赛时间:6月1日(周六)晚20:00 比赛链接:https://atcoder.jp/contests/abc356 2.ARC-179 比赛时间:6月2日(周日)晚20:00 …

【Go】十、路由配置以及ZAP 高性能日志库的使用

Project 目录创建 mxshop-api user-web api ---- 服务接口 config ---- 配置信息 forms ---- 表单验证信息 global ---- 全局信息 initialize ---- 初始化信息 middlewares ---- 中间件信息 proto ---- 数据信息 router ---- 路由信息 utils ---- 公用工具信息 validator ----…

excel导到access后长文本内容缺失

参考该文Excel表格如何导入Access数据库以及列内容超过255个字符被截断解决办法 - 知乎 原因是access数据中列内容超过255个字符会被截断。 解决方法:将该字段的数据类型修改为长文本即可。

微调真的能让LLM学到新东西吗:引入新知识可能让模型产生更多的幻觉

大型语言模型(llm)是在巨大的文本语料库上训练的,在那里他们获得了大量的事实知识。这些知识嵌入到它们的参数中,然后可以在需要时使用。这些模型的知识在培训结束时被“具体化”。在预训练结束时,模型实际上停止学习。 对模型进行对齐或进行…

【VTKExamples::Utilities】第十四期 Screenshot

很高兴在雪易的CSDN遇见你 VTK技术爱好者 QQ:870202403 公众号:VTK忠粉 前言 本文分享VTK样例Screenshot,保存窗口快照,并解析接口vtkWindowToImageFilter,希望对各位小伙伴有所帮助! 感谢各位小伙伴的点赞+关注,小易会继续努力分享,一起进步! 你的点赞就是…

SELINUX=enforcing时无法启动httpd服务的解决方案(semanage命令以及setroubleshoot-server插件的妙用)

一、问题描述: 当/etc/selinux/conf被要求必须是SELINUXenforcing,不被允许使用setenforce 0宽松模式 我们启动httpd就会报错: Job for httpd.service failed because the control process exited with error code. See "systemctl s…

如何安装ansible

ansible安装 1、 准备环境----关闭防护墙和selinux 一般用ansible不会少于10台以上 环境: 主机:4台 一个控制节点 3个被控制节点 解析:本地互相解析(所有机器) # vim /etc/hosts 192.168.1.10 ansible-web1 192.168.1.11 ansible-web2 192.168.1.12…

重生之 SpringBoot3 入门保姆级学习(08、properties 和 yml 表示复杂对象)

重生之 SpringBoot3 入门保姆级学习(08、properties 和 yml 表示复杂对象) 2.5 yml 配置文件2.6 复杂对象用 properties 表示2.7 复杂对象用 yml 表示 2.5 yml 配置文件 application.properties 配置文件书写形式 server.port9999spring.data.redis.hos…

Let‘s Encrypt 免费证书申请

填写邮箱,申请的域名 单域名:www.example.com 泛域名: *.example.com yum -y install certbot sudo certbot certonly --server https://acme-v02.api.letsencrypt.org/directory --manual --preferred-challenges dns --email xxexample…

第23讲:Ceph集群RBD块存储的离线备份与还原

文章目录 1.RBD块存储的离线备份机制2.RBD块存储的备份导出操作2.1.为RBD块存储设备创建一个快照2.2.基于快照文件备份到本地系统2.3.基于块设备备份到本地系统 3.RBD块存储的备份还原导入操作4.RBD块存储的增量备份与增量还原4.1.增量备份的操作4.2.增量备份的还原操作 1.RBD块…

从零开始学React--环境搭建

React官网 快速入门 – React 中文文档 1.搭建环境 下载nodejs,双击安装 nodejs下载地址 更新npm npm install -g npm 设置npm源,加快下载速度 npm config set registry https://registry.npmmirror.com 创建一个react应用 npx create-react-app react-ba…

Nginx的配置与调试

目录 1、安装Nginx 2、Nginx的配置文件结构 2.1 Nginx的全局配置 2.2 HTTP服务器配置 2.3 HttpGzip模块配置 2.4 负载均衡配置 2.5 server虚拟主机配置 2.6 location URL匹配配置 2.7 StubStatus模块配置 1、安装Nginx 在安装Nginx之前,需确保系统已经安装…

202303青少年软件编程(Python)等级考试试卷(四级)

第 1 题 【单选题】 运行下列程序, 输出的结果是? ( ) def wenhao(name = zhejiang):print(hello + name)wenhao()A :hello B :hellozhejiang C :helloname D :程序将提示运行错误 正确答案:B 试题解析: 定义函数时, 可以指定形参的默认值。 如果在调用函数时给函数…

SpringBoot如何使用日志Logback,及日志等级详解

Spring Boot默认已经集成了SLF4J(Simple Logging Facade for Java)作为日志的接口,以及Logback作为日志的实现。这意味着在大多数情况下,你无需做额外的配置即可开始记录日志。 下面是一个简要的指南,包括如何在Spring…

豆瓣内容抓取:使用R、httr和XML库的完整教程

概述 在数据分析和统计领域,R语言以其强大的数据处理能力和丰富的包库资源而闻名。它不仅提供了一个灵活的编程环境,还拥有专门用于数据抓取和处理的工具,如httr和XML库。这些工具使得从各种网站上抓取数据变得简单而高效。 豆瓣网站作为一个…

Android环境下Mesa初始化流程重学习之eglCreateContext

Mesa初始化流程重学习之eglCreateContext 引言 没有啥好说的了,直接上手撸代码!总得找点事情干不是!我打工我快乐!我奋斗,我快乐! 一. 核心结构体之间的关联 二. eglCreateContext流程分析 eglCreateContext(...)//s…

红酒配餐中的酒杯选择与使用技巧

在红酒配餐中,酒杯的选择与使用技巧是影响品鉴体验的重要因素。合适的酒杯不仅能展现出红酒的优雅和风味,还能提升用餐的仪式感和愉悦感。云仓酒庄雷盛红酒以其卓着的品质和丰富的口感,成为了红酒爱好者们的首要选择品牌。下面将介绍在红酒配…

21张让你代码能力突飞猛进Python速查表(神经网络、线性代数、可视化等)(有中文版)

随着深度学习的蓬勃发展,越来越多的小伙伴们开始使用python作为主打代码,python有着种类繁多的第三方库,这里为大家从网络上收集了一些代码速查表,希望可以帮你在码代码时提速。 基础 神经网络 线性代数 Python资料 可以去VX公…

python标准库argparse,脚本传参

argparse 是 Python 的标准库之一,它用于编写用户友好的命令行接口。通过 argparse,你可以很容易地为你的 Python 脚本添加命令行参数和选项,并解析它们。下面是一个简单的介绍和示例 # 导入库 import argparse# 定义命令行解析器对象 parse…

JavaScript 日期和时间的格式化

JavaScript 日期和时间的格式化 一、日期和时间的格式化 1、原生方法 1.1、使用 toLocaleString 方法 Date 对象有一个 toLocaleString 方法,该方法可以根据本地时间和地区设置格式化日期时间。例如: const date new Date(); console.log(date.toL…