Skip to main content
Version: 2.8.x(Latest)

gconv.Converter is a type conversion interface newly added in GoFrame v2.9, which provides type conversion capabilities through the creation of conversion objects, offering a more rigorous and flexible type conversion mechanism. Unlike traditional gconv package methods, the Converter interface returns an error when conversion fails, rather than defaulting to zero or empty values.

Features:

  1. Rigorous Error Handling: Returns error information when conversion fails, avoiding potential issues caused by silent failures
  2. Type Safety: Provides stricter type checking, reducing runtime errors
  3. Extensibility: Supports registering custom type conversion functions, adapting to complex business scenarios
  4. Consistent API: All conversion methods follow the same pattern, making usage more consistent
  5. Independent Instances: Multiple converter instances can be created, each with different configurations and registered conversion functions

Basic Introduction

The Converter interface is a composite interface that includes multiple sub-interfaces, providing comprehensive type conversion capabilities:

type Converter interface {
ConverterForConvert
ConverterForRegister
ConverterForInt
ConverterForUint
ConverterForTime
ConverterForFloat
ConverterForMap
ConverterForSlice
ConverterForStruct
ConverterForBasic
}

These sub-interfaces provide different types of conversion functions, for example:

  • ConverterForBasic: Basic type conversion (string, boolean, etc.)
  • ConverterForInt: Integer type conversion
  • ConverterForUint: Unsigned integer type conversion
  • ConverterForFloat: Floating-point type conversion
  • ConverterForTime: Time type conversion
  • ConverterForMap: Map type conversion
  • ConverterForSlice: Slice type conversion
  • ConverterForStruct: Struct type conversion
  • ConverterForConvert: Custom type conversion
  • ConverterForRegister: Register custom conversion functions

Creating a Converter Object

Use the gconv.NewConverter() function to create a new Converter object:

converter := gconv.NewConverter()

Basic Usage

Basic Type Conversion

package main

import (
"fmt"

"github.com/gogf/gf/v2/util/gconv"
)

func main() {
// Create a converter object
converter := gconv.NewConverter()

// Integer conversion
intValue, err := converter.Int("123")
if err != nil {
fmt.Println("Conversion failed:", err)
} else {
fmt.Println("Int conversion result:", intValue) // Output: 123
}

// Floating-point conversion
floatValue, err := converter.Float64("123.456")
if err != nil {
fmt.Println("Conversion failed:", err)
} else {
fmt.Println("Float64 conversion result:", floatValue) // Output: 123.456
}

// Boolean conversion
boolValue, err := converter.Bool("true")
if err != nil {
fmt.Println("Conversion failed:", err)
} else {
fmt.Println("Bool conversion result:", boolValue) // Output: true
}

// String conversion
strValue, err := converter.String(123)
if err != nil {
fmt.Println("Conversion failed:", err)
} else {
fmt.Println("String conversion result:", strValue) // Output: 123
}
}

Struct Conversion

package main

import (
"fmt"

"github.com/gogf/gf/v2/util/gconv"
)

type User struct {
Id int
Name string
Age int
}

func main() {
converter := gconv.NewConverter()

// Map to struct conversion
data := map[string]interface{}{
"id": 1,
"name": "John",
"age": 30,
}

var user User
err := converter.Struct(data, &user, gconv.StructOption{})
if err != nil {
fmt.Println("Conversion failed:", err)
} else {
fmt.Printf("Struct conversion result: %+v\n", user) // Output: {Id:1 Name:John Age:30}
}
}

Custom Type Conversion

Note: Custom type conversion is primarily used for conversion between complex types (such as structs, slices, maps, etc.), and does not support alias types of basic types. This is to improve conversion efficiency and avoid unnecessary performance overhead.

Here is an example of custom conversion using complex types:

package main

import (
"fmt"
"time"

"github.com/gogf/gf/v2/util/gconv"
)

// UserInfo custom type
type UserInfo struct {
ID int
Name string
Birthday time.Time
}

type UserDTO struct {
UserID string
UserName string
Age int
}

func userInfoT2UserDTO(in UserInfo) (*UserDTO, error) {
if in.ID <= 0 {
return nil, fmt.Errorf("invalid user ID: %d", in.ID)
}
// Calculate age
age := time.Now().Year() - in.Birthday.Year()
return &UserDTO{
UserID: fmt.Sprintf("U%d", in.ID),
UserName: in.Name,
Age: age,
}, nil
}

func main() {
converter := gconv.NewConverter()
// Register custom type conversion function - from UserInfo to UserDTO
err := converter.RegisterTypeConverterFunc(userInfoT2UserDTO)
if err != nil {
fmt.Println("Failed to register conversion function:", err)
return
}

// Use custom type conversion
userInfo := UserInfo{
ID: 101,
Name: "Zhang San",
Birthday: time.Date(1990, 5, 15, 0, 0, 0, 0, time.Local),
}

var userDTO UserDTO
err = converter.Scan(userInfo, &userDTO)
if err != nil {
fmt.Println("Conversion failed:", err)
} else {
fmt.Printf("Custom type conversion result: %#v\n", userDTO)
// Output similar to: Custom type conversion result: main.UserDTO{UserID:"U101", UserName:"Zhang San", Age:35}
}

// Test error handling
invalidUser := UserInfo{ID: -1, Name: "Invalid User"}
err = converter.Scan(invalidUser, &userDTO)
if err != nil {
fmt.Println("Expected error:", err) // Output error message: invalid user ID: -1
}
}

In the example above, we defined two complex types: UserInfo (source type) and UserDTO (target type), and registered a custom conversion function to convert UserInfo to UserDTO. This conversion is not just simple field mapping but also includes business logic (such as calculating age).

For more information about custom type conversion, please refer to the chapter: Type Conversion-Custom Type Conversion

Differences from Traditional gconv Package Methods

Error Handling

Traditional gconv package methods default to returning zero or empty values when conversion fails, without returning error information:

// Traditional method
value := gconv.Int("not-a-number") // Returns 0, no error

// Converter method
converter := gconv.NewConverter()
value, err := converter.Int("not-a-number") // Returns 0 and error information

Conversion Options

The methods of the Converter interface support more conversion option parameters, allowing for more fine-grained control of conversion behavior:

// Struct conversion options
structOption := gconv.StructOption{
Mapping: map[string]string{"ID": "UserId"},
RecursiveOption: gconv.RecursiveOptionTrue,
ContinueOnError: false,
PrivateAttribute: true,
}

// Use options for conversion
converter.Struct(data, &user, structOption)
Ask me