如何在 Golang 中将自定义结构的一部分复制到其他结构

How do I copy part of a custom struct to a different struct in Golang

提问人:SelfLearnedNoob 提问时间:10/6/2022 更新时间:10/6/2022 访问量:158

问:

我已经坚持了几个小时,希望你们中的一个人能帮助我找到一个优雅的解决方案。

基本上,我有以下结构:

type GetERC20TransferResponse struct {
Data struct {
    Address       string    `json:"address"`
    UpdatedAt     time.Time `json:"updated_at"`
    NextUpdateAt  time.Time `json:"next_update_at"`
    QuoteCurrency string    `json:"quote_currency"`
    ChainID       int       `json:"chain_id"`
    Items         []struct {
        BlockSignedAt    time.Time   `json:"block_signed_at"`
        BlockHeight      int         `json:"block_height"`
        TxHash           string      `json:"tx_hash"`
        TxOffset         int         `json:"tx_offset"`
        Successful       bool        `json:"successful"`
        FromAddress      string      `json:"from_address"`
        FromAddressLabel interface{} `json:"from_address_label"`
        ToAddress        string      `json:"to_address"`
        ToAddressLabel   interface{} `json:"to_address_label"`
        Value            string      `json:"value"`
        ValueQuote       float64     `json:"value_quote"`
        GasOffered       int         `json:"gas_offered"`
        GasSpent         int         `json:"gas_spent"`
        GasPrice         int64       `json:"gas_price"`
        FeesPaid         interface{} `json:"fees_paid"`
        GasQuote         float64     `json:"gas_quote"`
        GasQuoteRate     float64     `json:"gas_quote_rate"`
        Transfers        []struct {
            BlockSignedAt        time.Time   `json:"block_signed_at"`
            TxHash               string      `json:"tx_hash"`
            FromAddress          string      `json:"from_address"`
            FromAddressLabel     interface{} `json:"from_address_label"`
            ToAddress            string      `json:"to_address"`
            ToAddressLabel       interface{} `json:"to_address_label"`
            ContractDecimals     int         `json:"contract_decimals"`
            ContractName         string      `json:"contract_name"`
            ContractTickerSymbol string      `json:"contract_ticker_symbol"`
            ContractAddress      string      `json:"contract_address"`
            LogoURL              string      `json:"logo_url"`
            TransferType         string      `json:"transfer_type"`
            Delta                string      `json:"delta"`
            Balance              interface{} `json:"balance"`
            QuoteRate            float64     `json:"quote_rate"`
            DeltaQuote           float64     `json:"delta_quote"`
            BalanceQuote         interface{} `json:"balance_quote"`
            MethodCalls          interface{} `json:"method_calls"`
        } `json:"transfers"`
    } `json:"items"`
    Pagination struct {
        HasMore    bool        `json:"has_more"`
        PageNumber int         `json:"page_number"`
        PageSize   int         `json:"page_size"`
        TotalCount interface{} `json:"total_count"`
    } `json:"pagination"`
} `json:"data"`
Error        bool        `json:"error"`
ErrorMessage interface{} `json:"error_message"`
ErrorCode    interface{} `json:"error_code"`

现在,处理这些数据并不困难,但现在我正在尝试做一些我不确定是否可能的事情。基本上,我创建了另一个名为 Transfer 的结构:

type Transfer []struct {
BlockSignedAt        time.Time   `json:"block_signed_at"`
TxHash               string      `json:"tx_hash"`
FromAddress          string      `json:"from_address"`
FromAddressLabel     interface{} `json:"from_address_label"`
ToAddress            string      `json:"to_address"`
ToAddressLabel       interface{} `json:"to_address_label"`
ContractDecimals     int         `json:"contract_decimals"`
ContractName         string      `json:"contract_name"`
ContractTickerSymbol string      `json:"contract_ticker_symbol"`
ContractAddress      string      `json:"contract_address"`
LogoURL              string      `json:"logo_url"`
TransferType         string      `json:"transfer_type"`
Delta                string      `json:"delta"`
Balance              interface{} `json:"balance"`
QuoteRate            float64     `json:"quote_rate"`
DeltaQuote           float64     `json:"delta_quote"`
BalanceQuote         interface{} `json:"balance_quote"`
MethodCalls          interface{} `json:"method_calls"`

}

这只是回应的一部分。我需要的 Data.Items。现在我的问题是,如何从 GetERC20TransferReponse 结构中取出这部分,将其分离,然后返回。

流程是这样的:

  1. 查看 GetERC20TransferResponse 内部,查看 TransferType 的值。
  2. 根据 transfertype 执行操作/从响应中保存内容。Data.Items[1] / Transfer []struct 部分的 GetERC20TransferResponse

简而言之,非常优雅的是,当我调用检查 TransferType 是 0、1 还是 2 的函数时,它还将返回 GetERC20TransferResponse 结构的整个“Transfers”部分并返回它,这样我就不必再次访问该结构。

这是针对我正在开发的开源工具,出于速度原因,它需要在 Go 中(我相对较新)。

Go 多维阵列 结构 体切片 编组

评论


答:

0赞 Daniel Kiptoon 10/6/2022 #1

我建议首先将整个响应“GetERC20TransferResponse”分解为单独的结构体

// single transfer
type Transfer struct {
    BlockSignedAt        time.Time   `json:"block_signed_at"`
    TxHash               string      `json:"tx_hash"`
    FromAddress          string      `json:"from_address"`
    FromAddressLabel     interface{} `json:"from_address_label"`
    ToAddress            string      `json:"to_address"`
    ToAddressLabel       interface{} `json:"to_address_label"`
    ContractDecimals     int         `json:"contract_decimals"`
    ContractName         string      `json:"contract_name"`
    ContractTickerSymbol string      `json:"contract_ticker_symbol"`
    ContractAddress      string      `json:"contract_address"`
    LogoURL              string      `json:"logo_url"`
    TransferType         string      `json:"transfer_type"`
    Delta                string      `json:"delta"`
    Balance              interface{} `json:"balance"`
    QuoteRate            float64     `json:"quote_rate"`
    DeltaQuote           float64     `json:"delta_quote"`
    BalanceQuote         interface{} `json:"balance_quote"`
    MethodCalls          interface{} `json:"method_calls"`
}
    //single ERC items
type ERCItems struct {
    BlockSignedAt    time.Time   `json:"block_signed_at"`
    BlockHeight      int         `json:"block_height"`
    TxHash           string      `json:"tx_hash"`
    TxOffset         int         `json:"tx_offset"`
    Successful       bool        `json:"successful"`
    FromAddress      string      `json:"from_address"`
    FromAddressLabel interface{} `json:"from_address_label"`
    ToAddress        string      `json:"to_address"`
    ToAddressLabel   interface{} `json:"to_address_label"`
    Value            string      `json:"value"`
    ValueQuote       float64     `json:"value_quote"`
    GasOffered       int         `json:"gas_offered"`
    GasSpent         int         `json:"gas_spent"`
    GasPrice         int64       `json:"gas_price"`
    FeesPaid         interface{} `json:"fees_paid"`
    GasQuote         float64     `json:"gas_quote"`
    GasQuoteRate     float64     `json:"gas_quote_rate"`
    Transfers        []Transfer  `json:"transfers"`
}
//response data
type Data struct {
    Address       string     `json:"address"`
    UpdatedAt     time.Time  `json:"updated_at"`
    NextUpdateAt  time.Time  `json:"next_update_at"`
    QuoteCurrency string     `json:"quote_currency"`
    ChainID       int        `json:"chain_id"`
    Items         []ERCItems `json:"items"`
    Pagination    struct {
        HasMore    bool        `json:"has_more"`
        PageNumber int         `json:"page_number"`
        PageSize   int         `json:"page_size"`
        TotalCount interface{} `json:"total_count"`
    } `json:"pagination"`
}

//general response
type GetERC20TransferResponse struct {
    Data         Data        `json:"data"`
    Error        bool        `json:"error"`
    ErrorMessage interface{} `json:"error_message"`
    ErrorCode    interface{} `json:"error_code"`
}

这使您可以对响应对象进行细粒度控制。之后,您可以简单地使用一个函数来检查模型以检查转移类型并根据需要选择转移,例如

 func main() {
    response := GetERC20TransferResponse{}

    // get all items from the response
    items := response.Data.Items

    // slice to store transfers that match the required transfer type
    transfers := make([]Transfer, 0)

    // iterate through all items to and further iterate through all transfers adding
    // the whole transfers if any matches the required transfer types
    for _, item := range items {
        for _, transfer := range item.Transfers {
            if transfer.TransferType == "0" || transfer.TransferType == "1" || transfer.TransferType == "2" {
                transfers = append(transfers, item.Transfers...)
                break
            }
        }
    }

}

根据需要重构

评论

0赞 SelfLearnedNoob 10/6/2022
很有意思,谢谢!将按照您的建议实施它。