github.com/gogf/gf@v1.16.9/util/gutil/gutil_dump.go (about)

     1  // Copyright GoFrame Author(https://goframe.org). All Rights Reserved.
     2  //
     3  // This Source Code Form is subject to the terms of the MIT License.
     4  // If a copy of the MIT was not distributed with this file,
     5  // You can obtain one at https://github.com/gogf/gf.
     6  
     7  package gutil
     8  
     9  import (
    10  	"bytes"
    11  	"fmt"
    12  	"github.com/gogf/gf/internal/json"
    13  	"github.com/gogf/gf/util/gconv"
    14  	"os"
    15  	"reflect"
    16  )
    17  
    18  // apiVal is used for type assert api for Val().
    19  type apiVal interface {
    20  	Val() interface{}
    21  }
    22  
    23  // apiString is used for type assert api for String().
    24  type apiString interface {
    25  	String() string
    26  }
    27  
    28  // apiMapStrAny is the interface support for converting struct parameter to map.
    29  type apiMapStrAny interface {
    30  	MapStrAny() map[string]interface{}
    31  }
    32  
    33  // Dump prints variables <i...> to stdout with more manually readable.
    34  func Dump(i ...interface{}) {
    35  	s := Export(i...)
    36  	if s != "" {
    37  		fmt.Println(s)
    38  	}
    39  }
    40  
    41  // Export returns variables <i...> as a string with more manually readable.
    42  func Export(i ...interface{}) string {
    43  	buffer := bytes.NewBuffer(nil)
    44  	for _, value := range i {
    45  		switch r := value.(type) {
    46  		case []byte:
    47  			buffer.Write(r)
    48  		case string:
    49  			buffer.WriteString(r)
    50  		default:
    51  			var (
    52  				reflectValue = reflect.ValueOf(value)
    53  				reflectKind  = reflectValue.Kind()
    54  			)
    55  			for reflectKind == reflect.Ptr {
    56  				reflectValue = reflectValue.Elem()
    57  				reflectKind = reflectValue.Kind()
    58  			}
    59  			switch reflectKind {
    60  			case reflect.Slice, reflect.Array:
    61  				value = gconv.Interfaces(value)
    62  			case reflect.Map:
    63  				value = gconv.Map(value)
    64  			case reflect.Struct:
    65  				converted := false
    66  				if r, ok := value.(apiVal); ok {
    67  					if result := r.Val(); result != nil {
    68  						value = result
    69  						converted = true
    70  					}
    71  				}
    72  				if !converted {
    73  					if r, ok := value.(apiMapStrAny); ok {
    74  						if result := r.MapStrAny(); result != nil {
    75  							value = result
    76  							converted = true
    77  						}
    78  					}
    79  				}
    80  				if !converted {
    81  					if r, ok := value.(apiString); ok {
    82  						value = r.String()
    83  					}
    84  				}
    85  			}
    86  			encoder := json.NewEncoder(buffer)
    87  			encoder.SetEscapeHTML(false)
    88  			encoder.SetIndent("", "\t")
    89  			if err := encoder.Encode(value); err != nil {
    90  				fmt.Fprintln(os.Stderr, err.Error())
    91  			}
    92  		}
    93  	}
    94  	return buffer.String()
    95  }