|
1 | 1 | package v1 |
2 | 2 |
|
3 | 3 | import ( |
4 | | - "errors" |
| 4 | + "fmt" |
5 | 5 | "reflect" |
6 | 6 | ) |
7 | 7 |
|
8 | | -// Pipeline type. |
9 | | -type Pipeline func(...interface{}) (interface{}, error) |
| 8 | +// Pipeline define um pipeline que aceita argumentos iniciais e retorna um resultado ou erro. |
| 9 | +type Pipeline func(args ...interface{}) (interface{}, error) |
10 | 10 |
|
11 | | -// Pipe creates a pipeline from a series of functions. |
| 11 | +// Pipe cria um pipeline a partir de uma série de funções. |
| 12 | +// Cada função deve ter uma assinatura compatível com o encadeamento: |
| 13 | +// - Seus parâmetros serão preenchidos com os resultados da função anterior. |
| 14 | +// - Se uma função retornar um error não-nulo, o pipeline é interrompido. |
12 | 15 | func Pipe(fs ...interface{}) Pipeline { |
| 16 | + // Valida se todos os elementos são funções. |
| 17 | + for i, f := range fs { |
| 18 | + if reflect.TypeOf(f).Kind() != reflect.Func { |
| 19 | + panic(fmt.Sprintf("elemento na posição %d não é uma função", i)) |
| 20 | + } |
| 21 | + } |
| 22 | + |
| 23 | + // Obter o tipo que representa o interface error (para evitar repetir esse cálculo). |
| 24 | + errorType := reflect.TypeOf((*error)(nil)).Elem() |
| 25 | + |
13 | 26 | return func(initialArgs ...interface{}) (interface{}, error) { |
14 | 27 | currentArgs := initialArgs |
15 | | - for _, f := range fs { |
| 28 | + |
| 29 | + // Processa cada função do pipeline. |
| 30 | + for idx, f := range fs { |
16 | 31 | fnVal := reflect.ValueOf(f) |
17 | 32 | fnType := fnVal.Type() |
18 | 33 | numIn := fnType.NumIn() |
19 | 34 |
|
20 | | - // Prepare the input arguments for the current function. |
| 35 | + // Prepara os argumentos para a função atual. |
21 | 36 | in := make([]reflect.Value, numIn) |
22 | | - for i := range numIn { |
| 37 | + for i := 0; i < numIn; i++ { |
23 | 38 | if i < len(currentArgs) { |
24 | 39 | in[i] = reflect.ValueOf(currentArgs[i]) |
25 | | - } else if i < len(initialArgs) { // Allow passing manual arguments if not enough currentArgs. |
| 40 | + } else if i < len(initialArgs) { // fallback para os argumentos iniciais, se necessário |
26 | 41 | in[i] = reflect.ValueOf(initialArgs[i]) |
27 | 42 | } else { |
28 | | - // If there are not enough arguments to pass to the function, return an error. |
29 | | - return nil, errors.New("not enough arguments to pass to function") |
| 43 | + return nil, fmt.Errorf("argumentos insuficientes para a função na posição %d", idx) |
30 | 44 | } |
31 | 45 | } |
32 | 46 |
|
33 | | - // Call the current function in the pipeline. |
| 47 | + // Chama a função e obtém os resultados. |
34 | 48 | results := fnVal.Call(in) |
35 | 49 |
|
36 | | - // Assume the last function call results will be used as next input. |
37 | | - currentArgs = nil // Reset currentArgs for next function. |
38 | | - for _, result := range results { |
39 | | - if result.Type().Implements(reflect.TypeOf((*error)(nil)).Elem()) { |
40 | | - if !result.IsNil() { // If the result is an error, return it. |
41 | | - return nil, result.Interface().(error) |
| 50 | + // Prepara os argumentos para a próxima função, resetando currentArgs. |
| 51 | + currentArgs = make([]interface{}, 0, len(results)) |
| 52 | + for _, res := range results { |
| 53 | + // Se o resultado implementa error e não é nil, interrompe o pipeline. |
| 54 | + if res.Type().Implements(errorType) { |
| 55 | + if !res.IsNil() { |
| 56 | + return nil, res.Interface().(error) |
42 | 57 | } |
43 | | - // If it's a nil error, ignore it for the output. |
| 58 | + // Caso o error seja nil, não o adiciona aos resultados. |
44 | 59 | } else { |
45 | | - currentArgs = append(currentArgs, result.Interface()) |
| 60 | + currentArgs = append(currentArgs, res.Interface()) |
46 | 61 | } |
47 | 62 | } |
48 | 63 | } |
49 | 64 |
|
50 | | - // Return the final result which should match the last function's output type. |
| 65 | + // Se houver apenas um resultado, retorna-o diretamente; caso contrário, retorna um slice. |
51 | 66 | if len(currentArgs) == 1 { |
52 | | - return currentArgs[0], nil // Return single value if only one result. |
| 67 | + return currentArgs[0], nil |
53 | 68 | } |
54 | | - return currentArgs, nil // Return as slice if multiple values. |
| 69 | + return currentArgs, nil |
55 | 70 | } |
56 | 71 | } |
0 commit comments