巢狀結構體匯出excel的實現方式

2021-10-08 16:39:32 字數 3450 閱讀 3253

他的結構體是巢狀了另乙個匿名結構體, 即:

type a struct 

param := struct }

然後導致 writestruct 方法解析不出來, writestruct:

// writes a struct to row r. accepts a pointer to struct type 'e',

// and the number of columns to write, `cols`. if 'cols' is < 0,

// the entire struct will be written if possible. returns -1 if the 'e'

// doesn't point to a struct, otherwise the number of columns written

func (r *row) writestruct(e inte***ce{}, cols int) int

v := reflect.valueof(e).elem()

if v.kind() != reflect.struct

n := v.numfield() // number of fields in struct

if cols < n && cols > 0

var k int

for i := 0; i < n; i, k = i+1, k+1

case sql.nullbool:

cell := r.addcell()

if cell.setstring(``); t.valid

case sql.nullint64:

cell := r.addcell()

if cell.setstring(``); t.valid

case sql.nullfloat64:

cell := r.addcell()

if cell.setstring(``); t.valid

default:

switch f.kind()

} }return k

}

可以看到裡面只反**第一層, 如果裡面有巢狀結構的話就不會繼續遍歷, 所以導致巢狀結構體的字段值沒有寫入到excel中

通過檢視 writestruct 方法的原始碼檔案我們可以看到裡面還有乙個可用方法 writeslice:

// writes an array to row r. accepts a pointer to array type 'e',

// and writes the number of columns to write, 'cols'. if 'cols' is < 0,

// the entire array will be written if possible. returns -1 if the 'e'

// doesn't point to an array, otherwise the number of columns written.

func (r *row) writeslice(e inte***ce{}, cols int) int

// make sure 'e' is a ptr to slice

v := reflect.valueof(e)

if v.kind() != reflect.ptr

v = v.elem()

if v.kind() != reflect.slice

// it's a slice, so open up its values

n := v.len()

if cols < n && cols > 0

var setcell func(reflect.value)

setcell = func(val reflect.value)

case sql.nullbool:

cell := r.addcell()

if cell.setstring(``); t.valid

case sql.nullint64:

cell := r.addcell()

if cell.setstring(``); t.valid

case sql.nullfloat64:

cell := r.addcell()

if cell.setstring(``); t.valid

default:

switch val.kind()

} }var i int

for i = 0; i < n; i++

return i

}

這樣的話我們自己寫一套反射規則把結構體的值對映出來就好了

// structvaluetoslice 結構體值轉入slice

func structvaluetoslice(val inte***ce{}) (data inte***ce{}) else

for i := 0; i < v.numfield(); i++

} else

} return

}// recursionstructvaluetoslice 遞迴多層巢狀結構體的值轉入slice

func recursionstructvaluetoslice(val inte***ce{}, v reflect.value, data *inte***ce{}) else if reflect.valueof(val).type().kind() == reflect.struct else

for i := 0; i < v.numfield(); i++ else

} return

}

下面是單元測試

func teststructvaluetoslice(t *testing.t) 

param := struct }

t.log(structvaluetoslice(param))

}func testrecursionstructvaluetoslice(t *testing.t)

type b struct

param := struct }}

data := make(inte***ce{}, 0)

recursionstructvaluetoslice(param, reflect.value{}, &data)

t.log(data)

}

這樣的話就可以了, 插入之前先走下對映獲取到值的結構體切片, 然後再用 writeslice 方法寫入就可以了

看 writeslice 方法可以看出來它裡面也是反射獲取slice的值, 然後 r.addcell().cell.setvalue(t) 方法插進去了, 所以想提公升效率的話可以直接在反射的方法裡直接將值寫入行就行了, 省了一步反射的過程

結構體巢狀結構體名

結構體巢狀結構體名 前一段時間在看ddk中例子的時候,看到這樣的的結構體定義 typedef struct common device data common device data,pcommon device data typedef struct pdo device data pdo dev...

結構體中巢狀結構體

結構體的巢狀問題 結構體的自引用 self reference 就是在結構體內部,包含指向自身型別結構體的指標。結構體的相互引用 mutual reference 就是說在多個結構體中,都包含指向其他結構體的指標。1.1不使用typedef時 錯誤的方式 struct tag 1 這種宣告是錯誤的,...

巢狀結構體案例

這個案例還是有很多地方可以學習的,決定記錄一下 參考 黑馬程式設計師匠心之作 c 教程從0到1入門程式設計 include include include include using namespace std 定義結構體 struct student struct teacher 賦值函式 voi...