GoLand 开发报错:reflect.Value.Interface: cannot return value obtained from unexported field or method
该报错是因为在调用 reflect.Value.Interface() 方法时,返回了一个未公开的字段或方法。具体来说,可能是在使用反射获取某些结构体字段或方法时,该字段或方法被声明为私有的,因此在使用 reflect.Value.Interface() 方法时就会出现该错误。
在这段代码中,可能是在调用 proto.Merge() 方法时,传入的参数中包含了未公开的字段或方法,因此反射时就会出现该错误。
解决方法:
- **检查代码中的结构体定义:**确保所有需要通过反射访问的字段或方法都声明为公开的,即字段或方法名首字母大写。
- 避免使用反射获取私有字段或方法: 如果需要访问私有字段或方法,建议使用其他方式,例如通过公共方法进行访问。
- 使用
reflect.FieldByName或reflect.MethodByName获取字段或方法: 这两种方法可以用来获取结构体中的字段或方法,即使它们是私有的。 - 使用
reflect.CanInterface检查字段或方法是否可反射: 该方法可以用来判断字段或方法是否可以被反射访问。
示例代码:
// batchGetOrderInfoList 批量请求云rpc接口,控制并发数N
func batchGetOrderInfoList(ctx context.Context, uin string, orders []*pb.OrderListDetails,
returnOrderList *[]*pb.OrderListDetails) ([]string, error) {
failedTsIds := make([]string, 0)
tasks := make([]func() error, 0)
for i := 0; i < len(orders); i++ {
order := orders[i]
// 创建任务
task, failedTsId := createTask(ctx, uin, order, returnOrderList)
tasks = append(tasks, task)
if failedTsId != '' {
failedTsIds = append(failedTsIds, failedTsId)
}
}
return failedTsIds, util.GoAndWait(10, tasks...)
}
func createTask(ctx context.Context, uin string, order *pb.OrderListDetails,
returnOrderList *[]*pb.OrderListDetails) (func() error, string) {
log.InfoContextf(ctx, '查询按消费明细开票信息-子任务, 订单号=%v', order.GetSubOrderNo())
failedTsId := ''
task := func() error {
//预设置失败订单号,如无失败返回时设置为空
failedTsId = order.GetSubOrderNo()
// 请求云接口按照订单号获取订单的未开票金额、已开票金额
GetInvoiceOrderListRsp, err := cloudBilling.GetInvoiceOrderList(ctx, uin, 1, 1, order.GetSubOrderNo())
if err != nil {
log.ErrorContextf(ctx, 'createTask qcloud.invoice.GetOrderInfoList.err, sub_order_no=%+v', order.GetSubOrderNo())
return err
}
log.InfoContextf(ctx, 'GetInvoiceOrderList.Rsp=%+v', GetInvoiceOrderListRsp)
log.InfoContextf(ctx, 'GetInvoiceOrderList.Rsp=%v', GetInvoiceOrderListRsp)
if GetInvoiceOrderListRsp == nil {
return errors.New('云接口数据异常,GetInvoiceOrderListRsp is nil')
}
if GetInvoiceOrderListRsp.ReturnCode != 0 {
log.ErrorContextf(ctx, 'GetInvoiceOrderList.Rsp.err=%v', GetInvoiceOrderListRsp.ReturnMessage)
return errors.New(GetInvoiceOrderListRsp.ReturnMessage)
}
log.InfoContextf(ctx, 'GetInvoiceOrderListRsp.Data.Detail')
detailList := GetInvoiceOrderListRsp.Data.Detail
if len(detailList) == 0 {
return errors.New('云接口数据异常,订单数量为0')
}
if len(detailList) > 0 {
returnOrder := &pb.OrderListDetails{}
proto.Merge(returnOrder, order)
log.InfoContextf(ctx, 'GetInvoiceOrderList len(detailList)')
// 追加订单字段
*returnOrder.UnInvoiceAmt = detailList[0].UnInvoiceAmount
*returnOrder.InvoiceAmt = detailList[0].InvoicedAmount
*returnOrderList = append(*returnOrderList, returnOrder)
//无失败返回时设置为空
failedTsId = ''
}
log.InfoContextf(ctx, 'order=%+v', order)
log.InfoContextf(ctx, 'order=%v', order)
return nil
}
log.InfoContextf(ctx, 'task=%+v, failedTsId=%v', task, failedTsId)
return task, failedTsId
}
注意:
- 该错误可能与 proto.Merge() 方法的具体实现有关,建议仔细检查 proto.Merge() 方法的文档和代码。
- 如果无法确定问题所在,建议提供更多代码片段和错误信息,以便更好地分析问题。
- 在使用反射时,应谨慎操作,避免潜在的安全风险。
原文地址: https://www.cveoy.top/t/topic/oBJP 著作权归作者所有。请勿转载和采集!