Solidity开发智能合约

05-Solidity开发智能合约

0 Solidity和智能合约

Solidity开发可运行的智能合约步骤:

  1. 源代码通过编译成字节码(Bytecode),同时会产生二进制接口规范(ABI)
  2. 通过交易将字节码部署到以太坊网络,部署成功会产生一个智能合约账户
  3. 通过web3.js+ABI去调用智能合约中的函数来实现数据的读取和修改

下面开始简单例子入手Solidity。

1 以太坊的前端 API

1.1 Web3.js

地址:

alt

安装:

npm install web3

使用方法:

// In Node.js
const Web3 = require('web3');
const web3 = new Web3('ws://localhost:8546');
console.log(web3);
// Output
{
    eth: ...,
    shh: ...,
    utils: ...,
}

也可像以下方法使用:

import Web3 from 'web3';
import { BlockHeader, Block } from 'web3-eth' // ex. package types
const web3 = new Web3('ws://localhost:8546');

使用举例:

web3.eth.getAccounts().then(console.log);

1.2 Ethereumjs

以太坊的实用程序功能集合,如ethereumjs-util和ethereumjs-tx,github:

alt

安装:

npm install ethereumjs-util

使用方法:

import assert from 'assert'
import { isValidChecksumAddress, unpadBuffer, BN } from 'ethereumjs-util'

const address = '0x2F015CG60E0be116B1f0CD534704Dd9c92118FB6A'
assert.ok(isValidChecksumAddress(address))

assert.equal(unpadBuffer(Buffer.from('000000006600''hex'), Buffer.from('6600''hex'))
             
assert.equal(new BN('dead'16).add(new BN('101010'2)), 57047)
Ethereumjs-API

Account class:私钥/公钥和地址相关功能 (创建、验证、转换)

举例: Const generateAddress2

generateAddress2(from: Buffer, salt: Buffer, initCode: Buffer): Buffer

NameTypeDescription
fromBuffer谁开始创建新地址
saltBuffer加盐
initCodeBuffer创建合约的初始代码
ethereumjs-wallet

ethereumjs-wallet: 轻量级钱包实现:

alt

目前,它支持密钥创建和各种格式之间的转换。

使用方法:

import Wallet from 'ethereumjs-wallet' Thirdparty API: import { thirdparty } from 'ethereumjs-wallet' HD Wallet API: import { hdkey } from 'ethereumjs-wallet'

其他常用接口
  • light.js - 为轻客户端优化的高级反式JS库
  • flex-contract 和 flex-ether - 零配置的高级库,用于与智能合约进行交互并进行交易
  • ez-ens - ens-简单的零配置以太坊域名服务地址解析器
  • web3x - web3.js的TypeScript端口。好处包括小巧的构造和全类型的安全性,包括与合同进行交互时的安全性
  • Nethereum - 跨平台的以太坊开发框架
  • Tasit SDK - 一个React Native库,使用在移动端与以太坊进行交互
  • Delphereum - 以太坊区块链的Delphi接口,允许开发适用于Windows,macOS,iOS和Android的dApp开发
  • Fortmatic - 一种易于使用的SDK,无需扩展或下载即可构建web3 dApp
  • Portis - 具有SDK的非托管钱包,可轻松与DApp进行交互而无需安装任何东西

2 以太坊的后端 API

2.1 Web3.py - Python Web3

需要Python 3.7.2+

安装:

pip install web3

测试Provider:

>>> from web3 import Web3, EthereumTesterProvider
>>> w3 = Web3(EthereumTesterProvider())
>>> w3.isConnected()
True

local Provider:

>>> from web3 import Web3
# IPCProvider:
>>> w3 = Web3(Web3.IPCProvider('/path/to/geth.ipc'))
# HTTPProvider:
>>> w3 = Web3(Web3.HTTPProvider('http://127.0.0.1:8545'))
# WebsocketProvider:
>>> w3 = Web3(Web3.WebsocketProvider('wss://127.0.0.1:8546'))
>>> w3.isConnected()
True

获取最后的区块

web3.eth.get_block("latest")

获取区块number

web3.eth.block_number

检查账户余额

# 输入钱包地址
web3.eth.get_balance('0x742d35Cc6634C0532925a3b844Bc454e4438f44e')

2.2 Web3j:Java Ethereum Dapp API

轻量级、高度模块化、反应式、类型安全的Java和Android库,用于处理智能合约并与以太坊网络上的客户端(节点)集成。

运行时的依赖:

  • RxJava:反应式扩展的Java-VM实现,一个库,用于使用可观察序列组合异步和基于事件的程序
  • OKHttp:默认情况下高效的HTTP客户端
  • Jackson Core : 快速J将SON序列化/反序列化
  • Bouncy Castle : (Android上的Spongy Castle )用于加密
  • Jnr-unixsocket:类Unix系统的IPC(Android上不可用)
  • Java-WebSocket:该存储库包含一个纯Java编写的基本WebSocket服务器和客户端实现。底层类是用java实现的。它允许非阻塞事件驱动模型(类似于web浏览器的WebSocket API)。

Java:

<dependency>
    <groupId>org.web3j</groupId>
    <artifactId>core</artifactId>
    <version>4.8.7</version>
    </dependency>

Android:

<dependency>
    <groupId>org.web3j</groupId>
    <artifactId>core</artifactId>
    <version>4.8.7-android</version>
    </dependency>

2.3 Ethereum-php

Ethereum JSON-RPC API的类型,支持PHP-7.1+。

在composer.json文件中添加类库

{
    "minimum-stability""dev",
    "autoload": {
        "psr-4": {
            "Ethereum\\\": "src/"
        }
    },
    "
repositories": [
        {
            "
type": "git",
            "
url": "https://github.com/digitaldonkey/ethereum-php.git"
        }
    ],
    "require": {
        "digitaldonkey/ethereum-php""dev-master"
    }
}

用法:composer require digitaldonkey/ethereum-php

require __DIR__.'/vendor/autoload.php';
use Ethereum\Ethereum;
try {
    // Connect to Ganache
    $eth = new Ethereum('http://127.0.0.1:7545');
    // Should return Int 63
    echo $eth->eth_protocolVersion() ->val();
}
catch (\Exception $exception) {
    die("Unable to connect.");
}

其它

  • Nethereum - .Net Web3
  • Ethereum.rb - Ruby Web3
  • Eventeum - 由Kauri用Java编写的以太坊智能合约事件和后端微服务之间的桥梁
  • Ethereum-jsonrpc-gateway - 一个网关,允许您运行多个以太坊节点以实现冗余和负载平衡。可以作为Infura的替代品(或在其之上)运行。用Golang写的
  • Ethereum Contract Service - 一种MESG服务,可根据其地址和ABI与任何以太坊合约进行交互
  • Ethereum Service - 一种MESG服务,用于与以太坊中的事件进行交互并与其进行交互
  • Marmo - Python, JS和Java SDK,以简化与以太坊的交互。使用中继器将交易成本分担给中继器

3 开发环境部署

3.1 npm

Node Package Manager,一个软件包管理系统,专管理用 js 编写的软件包。可免费下载别人写好的js软件包,并用到项目中,当然也可以上传共享自己写的js软件包。

Node.js内置npm,只要安装node.js,就可直接使用npm。

node官网: https://nodejs.org/en/

安装完 node.js 后,把npm更新到最新版本:

npm install npm@latest -g
项目使用npm
  1. 初始化:根据提示填写信息,即可产生package.json文件 cd <项目根目录> npm init
  2. 使用npm下载安装包

安装需要使用的包

npm install lodash

安装完成后,package.json中会添加版本信息,如下:

{
    "dependencies": {
        "lodash""^1.0.0"
    }
}

使用安装的包:

var lodash = require('lodash');
var output = lodash.without([1,2,3],1);
console.log(output);

更新包

法一:根据版本号更新

npm install lodash@版本号

法二:更新最新版本

- npm install lodash
- npm install lodash@latest

法三:修改package.json中包的版本号,下次npm install会自动更新会修改后的版本。

npm常用命令
#全局安装 lodash
npm install -g lodash

#本地安装 lodash(默认安装最新版本)
npm install lodash
npm install lodash@latest

#安装指定版本
npm install lodash@1.0.0

#卸载
npm uninstall lodash

#查看已安装
npm ls

#更新 lodash 到最新版本
npm update lodash

#搜索 lodash
npm search lodash
常见错误

Error: Cannot find moduel

packages 没有被安装

解决方法:

# 无作用域包安装
npm install <package_name>

# 有作用域包安装
npm install <@scope/package_name>

安装出错,错误提示:npm resource busy or locked...

可先清除再重新安装

npm cache clean

npm install
版本控制符

版本号由三位数字组成(例如:1.2.3):

  • 第一位表示主版本
  • 第二位表示次要版本
  • 第三位表示补丁版本
^表示用于确定主版本号,~用于确定主版本号+次要版本号

^1:等同于1.xx,以1开头所有版本

~2.2:等同于2.2.x,以2.2开头所有版本

~2.2.1:以2.2开头,且最后一位补丁号≥1的所有版本,即2.2.1与2.2.9之间版本,包括头尾

如:

"dependencies": {
  "my_dep""^1.0.0",
  "another_dep""~2.2.0"
},

3.2 Ganache(过时)

运行在PC上的以太坊开发者的个人区块链。

Ganache,Truffle Suite的一部分,通过把合约和交易放到前面来简化dapp的开发。

用Ganache可快速看到你的应用咋影响区块链的。细节如:你的账户、余额、合约及Gas成本。也可调整Ganache的采矿控制来更好的适用你的应用。

Ganache为那些不在GUI工作的人提供一个命令行工具。非常适合自动化测试和持续集成的环境。

sodu npm install -g ganache-cli

安装完成后命令行输入

$ ganache-cli

查看是否安装成功

启动ganache-cli指令:

ganache-cli

图形界面的版本,下载地址:https://github.com/trufflesuite/ganache/releases

Ganache常见命令参数

调整挖矿时间(Ganache默认是在交易产生时进行挖矿):

//10秒产生一个区块
ganache-cli -b 10

指定主机端口与网络ID:

//指定IP,端口及网络ID
ganache-cli -h 127.0.0.1 -p 8545 -i 8888

设置gas价格和gas上限:

ganache-cli -g 20000000
ganache-cli -l 10000000

输出RPC调用请求体:

ganache-cli -v

-v不是version缩写,而是verbose的意思,RPC调用默认只输出方法名,如eth_getBlockByNumber,而使用-v则会输出请求体

常见命令参数

指定默认生成账户的以太币:

ganache-cli -e 1000

指定默认生成的账户数量:

ganache-cli -a 50

助记词相关:

ganache-cli -d
ganache-cli -m "boil razor arrest first space chicken social explain leader soon unique upset"
ganache-cli -s "hello"


-d: 让Ganache启动节点时使用固定的预定义助记词,这样其他连接Ganache的轻钱包不用每次重新导入助记词。
-m: 可指定助记词,使用相同的助记词会生成一个相同的HD钱包;
-s: 指定一个种子用来生成助记词,然后使用助记词生成HD钱包,相同的种子会产生相同的助记词从而生成相同的HD钱包。

锁定和解锁账户:

# 使用--secure --unlock
ganache-cli --secure --unlock "0x67a3119994ffc7b384e086e443bf7a73a96a45c06ae3d1b163586ebc8e6f22"
--unlock "0xac0603889ceee85ff0075de364d4fc92d383cecc57c2a2c3465404c8296feab15"

# 或用-n -u
ganache-cli -n -u 0 -u 1

指定账户:

ganache-cli --account="<privatekey>",balance" [--account="<privatekey>",balance"]
在工程中启动Ganache的server

Ganache除了可以直接提供Provider之外,还可以作为一个HTTP Server,这样其他的一些服务或者应用就可以通过HTTP的方式调用对应的接口。使用非常简单,我们使用上面建立的工程,不过要添加一个依赖CircularJSON,执行下面的命令安装

npm i circular-json -S

在工程中启动Ganache的server,然后在工程目录下面创建一个server.js文件:

// 读写文件
const fs = require('fs');
// 提供测试服务
const ganache = require("ganache-cli");
// 格式化输对像
const CircularJSON = require('circular-json');
var server = ganache.server();
// 监听8545端口
server.listen(8545function(err, blockchain){
    console.log(err);
    console.log(blockchain)
    // fs.writeFileSync('blockchain.txt', CircularJSON.stringify(blockchain));
    // 输出ganache-cli中区块链数据结构及内容到blockchain文件中
    fs.writeFileSync('blockchain.txt', CircularJSON.stringify(blockchain, null'\t')
    // 打印钱包助记词
    console.log(blockchain.mnemonic);
});

启动服务器不需要web3.js,但是需要文件,所以引入Node.js的ts模块和circular-json将对象转换为字符串,因为对象中有循环引用,所以不能直接使用JSON,而是使用了CircularJSON。

上面设置监听端口8545,回调函数中我们打印了一下blockchain的助记词,当然也可以打印其他blockchain中的数据。blockchain的数据比较多,所以没有直接使用console输出,而是写入blockchain.txt文件中,多看这个文件有助于理解以太坊区块链数据结构。

因为数据比较多,这里就不一一给出blockchain的数据了,感兴趣可以自己动手试一试,然后看一下blockchain文件中的数据。

配置工程中依赖的Ganache

Ganache作为工程依赖的配置和命令行使用命令参数基本一致,以下为Ganache工程依赖常用的配置

参数说明
accounts和命令行的--accounts相同
logger实现了log方法的对象,例如console,用于输出日志
mnemonic字符串,设置助记词
port整数,设置端口
seed字符串,设置种子
total_accounts数字类型,账号数量
default_balance_ether每一个生成账户,默认的以太坊数量
network_id整数,网络ID
blockedboolean值,是否锁定账户
unlocked_accounts数组,不确定账户、地址或者索引值
db_path区块数据存放位置

Geth

又名Go Ethereum,是以太坊协议的三种实现之一,由Go语言开发,完全开源的项目。Geth可以被安装在很多操作系统上,包括Windows、Linux、Mac的OSX、Android或者IOS系统. Geth官网: https://geth.ethereum.org/:

alt

Geth的Github地址: https://github.com/ethereum/go-ethereum:

alt

作者: DeeLThink https://www.bilibili.com/read/cv16165148

输入 geth version,检查是否安装成功

Geth常用命令

USAGE

geth [options] command [command options] [arguments...]:geth [选项] 命令 [命令选项][参数...]

COMMANDS

account  Manage accounts
//管理账户
attach    Start an interactive JavaScript environment (connect to node)
//启动交互式JavaScript环境(连接到节点)
bug       opens a window to report a bug on the geth repo
//给github源代码仓库提issue,提交bug
console   Start an interactive JavaScript environment
//启动交互式JavaScript环境
copydbCreate a local chain from a target chaindata folder //从文件夹创建本地链
dumpDump a specific block from storage //Dump(分析)一个特定的块存储
dumpconfigShow configuration values
exportExport blockchain into file
importImport a blockchain file
initBootstrap and initialize a new genesis block
jsExecute the specified JavaScript files //执行指定的JavaScript文件(多个)
license   Display license information    //显示许可信息
makecache Generate ethash verification cache (for testing)   //生成ethash验证缓存(用于测试)
makedag Generate ethash mining DAG (for testing)   //生成ethash挖矿DAG(用于测试)
monitor Monitor and visualize node metrics    //监控和可视化节点指标
removedb Remove blockchain and state databases   //删除区块链和状态数据库
version Print version numbers    //打印版本号
wallet Manage Ulam presale wallets   //管理Ethereum预售钱包
help, h Shows a list of commands or help for one command   //显示一个命令或帮助一个命令列表

4 投票的例子

以下是一个简单的Solidity合约示例,它实现了电子投票的功能。这个合约的主要目标是确保投票权被正确分配,并防止被操纵。 首先,我们创建了一个委托投票机制,允许选民将他们的投票权委托给他们信任的人。为了做到这一点,我们需要为每个选民(即“表决”)创建一个独立的地址,并赋予他们投票权。然后,作为合约的创造者——即“主席”,我们将为每个选项提供一个简称为“winningProposal()”的函数,用于返回获得最多投票的提案。 在投票时间结束时,“winningProposal()”函数会返回获得最多投票的提案,从而实现电子投票的功能。

pragma solidity ^0.4.22
//@title 委托投票

contract Ballot{  
    //这里声明了一个新的复合类型用于稍后的变量  
    //它用来表示一个选民  
    struct Voter {  
        uint weight; //计票的权重  
        bool voted; //若为真,代表该人已投票  
        address delegate; //被委托人  
        uint vote; //投票提案的索引  
    }  
    //提案的类型  
    struct Proposal {  
        bytes32 name; //简称(最长32个字节)  
        uint voteCount; //得票数  
    }

    address public chairperson;

    // 这声明了一个状态变量,为每个可能的地址存储一个 `Voter`。
    mapping(address => Voter) public voters;

    // 一个 `Proposal` 结构类型的动态数组
    Proposal[] public proposals;

    // 为 `proposalNames` 中的每个提案,创建一个新的(投票)表决
    constructor(bytes32[][] proposalNames) public {
        chairperson = msg.sender;
        voters[chairperson].weight = 1;
        //对于提供的每个提案名称,
        //创建一个新的 Proposal 对象并把它添加到数组的末尾。
        for (uint i = 0; i < proposalNames.length; i++) {
            // `Proposal({...})` 创建一个临时 Proposal 对象,
            // `proposals.push({...})` 将其添加到 `proposals` 的末尾
            proposals.push(Proposal({
                name: proposalNames[i],
                voteCount: 0
            }));
        }
    }

    // 授权 `voter` 对这个(投票)表决进行投票
    // 只有 `chairperson` 可以调用该函数
    function giveRightToVote(address voter) public {
        // 若 `require` 的第一个参数的计算结果为 `false`,
        // 则终止执行,撤销所有对状态和以太币余额的改动。
        // 在旧版的 EVM 中这曾经会消耗所有 gas,但现在不会了。
        // 使用 require 来检查函数是否被正确地调用,是一个好习惯。
        // 你也可以在 require 的第二个参数中提供一个对错误情况的解释。
        require(
            msg.sender == chairperson,
            "Only chairperson can give right to vote."
        );

        require(
            !voters[voter].voted,
            "The voter already voted."
        );

        require(voters[voter].weight == 0);
        voters[voter].weight = 1;
    }

    //把你的投票委托到投票者 `to`。
    function delegate(address to) public {
        //传引用
        Voter storage sender = voters[msg.sender];
        require(!sender.voted, "You already voted.");
        require(to != msg.sender, "Self-delegation is disallowed.");

        //委托是可以传递的,只要被委托者 `to` 也设置了委托。
        //一般来说,这种循环委托是危险的。因为,如果传递的链条太长,则可能需消耗的gas要多于区块中剩余的(大于区块设置的gasLimit),这种情况,委托不会被执行。
        //而在另一些情况下,如果形成闭环,则会让合约完全卡住。
        while (voters[to].delegate != address(0)) {
            to = voters[to].delegate;
        }
        //不允许闭环委托
        require(to != msg.sender, "Found loop in delegation.");

        // `sender` 是一个引用,相当于对 `voters[msg.sender].voted` 进行修改
        sender.voted = true;
        sender.delegate = to;
        Voter storage delegate_ = voters[to];
        if (delegate_.voted) {
            // 若被委托者已经投过票了,直接增加得票数
            proposals[delegate_.vote].voteCount += sender.weight;
        } else {
            // 若被委托者还没投票,增加委托者的权重
            delegate_.weight += sender.weight;
        }
    }

    //把你的票(包括委托给你的票),  
    //投给提案 `proposals[proposal].name`.  
    function vote(uint proposal) public {  
        Voter storage sender = voters[msg.sender];  
        require(!sender.voted, "Already voted.");  
        sender.voted = true;  
        sender.vote = proposal;

        //如果 `proposal` 超过了数组的范围,则会自动抛出异常,并恢复所有的改动  
        proposals[proposal].voteCount += sender.weight;  
    }

    //@dev 结合之前所有的投票,计算出最终胜出的提案  
    function winningProposal() public view  
    returns (uint winningProposal_)  
    {  
        uint winningVoteCount = 0;  
        for (uint p = 0; p < proposals.length; p++) {  
            if (proposals[p].voteCount > winningVoteCount) {  
                winningVoteCount = proposals[p].voteCount;  
                winningProposal_ = p;  
            }  
        }
    }

    //调用winningProposal()函数以获取提案数组中获胜者的索引,并以此返回获胜者的名称
    function winnerName() public view
        returns (bytes32 winnerName_)
    {
        winnerName_ = proposals[winningProposal()].name;
    }
}

参考:

  • https://github.com/MetaMask

获取更多干货内容,记得关注我哦。

本文由 mdnice 多平台发布

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/927894.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Java基础之控制语句:开启编程逻辑之门

一、Java控制语句概述 Java 中的控制语句主要分为选择结构、循环结构和跳转语句三大类&#xff0c;它们在程序中起着至关重要的作用&#xff0c;能够决定程序的执行流程。 选择结构用于根据不同的条件执行不同的代码路径&#xff0c;主要包括 if 语句和 switch 语句。if 语句有…

Vue教程|搭建vue项目|Vue-CLI2.x 模板脚手架

一、项目构建环境准备 在构建Vue项目之前&#xff0c;需要搭建Node环境以及Vue-CLI脚手架&#xff0c;由于本篇文章为上一篇文章的补充&#xff0c;也是为了给大家分享更为完整的搭建vue项目方式&#xff0c;所以环境准备部分采用Vue教程&#xff5c;搭建vue项目&#xff5c;V…

shell脚本30个案例(五)

前言&#xff1a; 通过一个多月的shell学习&#xff0c;总共写出30个案例&#xff0c;分批次进行发布&#xff0c;这次总共发布了5个案例&#xff0c;希望能够对大家的学习和使用有所帮助&#xff0c;更多案例会在下期进行发布。 案例二十一、系统内核优化 1.问题&#xff1…

分布式集群下如何做到唯一序列号

优质博文&#xff1a;IT-BLOG-CN 分布式架构下&#xff0c;生成唯一序列号是设计系统常常会遇到的一个问题。例如&#xff0c;数据库使用分库分表的时候&#xff0c;当分成若干个sharding表后&#xff0c;如何能够快速拿到一个唯一序列号&#xff0c;是经常遇到的问题。实现思…

ChatGPT/AI辅助网络安全运营之-数据解压缩

在网络安全的世界中&#xff0c;经常会遇到各种压缩的数据&#xff0c;比如zip压缩&#xff0c;比如bzip2压缩&#xff0c;gzip压缩&#xff0c;xz压缩&#xff0c;7z压缩等。网络安全运营中需要对这些不同的压缩数据进行解压缩&#xff0c;解读其本意&#xff0c;本文将探索一…

C++小问题

怎么分辨const修饰的是谁 是限定谁不能被改变的&#xff1f; 在C中&#xff0c;const关键字的用途和位置非常关键&#xff0c;它决定了谁不能被修改。const可以修饰变量、指针、引用等不同的对象&#xff0c;并且具体的作用取决于const的修饰位置。理解const的规则能够帮助我们…

Docker中配置Mysql主从备份

Mysql配置主从备份 一、Docker中实现跨服务器主从备份二、配置步骤1.配置主库2.配置从库3.遇到问题3.其它使用到的命令 一、Docker中实现跨服务器主从备份 在 Docker 中配置 MySQL 主从备份主要通过 MySQL 主从复制实现 二、配置步骤 1.配置主库 # 进入mysql主库容器 docke…

下载maven 3.6.3并校验文件做md5或SHA512校验

一、下载Apache Maven 3.6.3 Apache Maven 3.6.3 官方下载链接&#xff1a; 二进制压缩包&#xff08;推荐&#xff09;: ZIP格式: https://archive.apache.org/dist/maven/maven-3/3.6.3/binaries/apache-maven-3.6.3-bin.zipTAR.GZ格式: https://archive.apache.org/dist/…

C++趣味编程:基于树莓派Pico的模拟沙漏-倾斜开关与LED的互动实现

沙漏,作为一种古老的计时工具,利用重力让沙子通过狭小通道,形成了计时效果。在现代,我们可以通过电子元件模拟沙漏的工作原理。本项目利用树莓派Pico、倾斜开关和LED,实现了一个电子沙漏。以下是项目的详细技术解析与C++代码实现。 一、项目概述 1. 项目目标 通过倾斜开关…

pycharm链接neo4j(导入文件)

1.新建csv文件 2.写入文件 3.运行代码 import csv from py2neo import Graph, Node, Relationship# 连接到Neo4j数据库&#xff0c;使用Bolt协议 graph Graph("bolt://localhost:7687", auth("neo4j", "password"))# 读取CSV文件 with open(…

【C++】多线程

目录 一 概念 1 多线程 2 多进程与多线程 3 多线程理解 二 创建线程 1 thread 2 join() 和 detach() 3 this_thread 三 std::mutex 1 lock 和 unlock 2 lock_guard 3 unique_lock 四 condition_variable 五 std::atomic 一 概念 1 多线程 在C11之前&#xff0…

Kafka 图形化工具 Eagle安装

Kafka 图形化工具 Eagle 3.0.1版本安装 1、安装JDK jdk安装 2、安装kafka 如未安装kafka&#xff0c;需要先安装完kafka 3、下载kafka-eagle 官网下载地址 wget https://github.com/smartloli/kafka-eagle-bin/archive/v3.0.1.tar.gz #移动到安装目录 mv v3.0.1.tar.gz…

vue实现echarts饼图自动轮播

echarts官网&#xff1a;Examples - Apache ECharts echartsFn.ts 把echarts函数封装成一个文件 import * as echarts from "echarts";const seriesData [{"value": 12,"name": "过流报警"},{"value": 102,"name&qu…

CSS动画案例6

目录 一、介绍二、静态页面的布局1.HTML部分2.CSS 三、动画交互四、结束语 一、介绍 本节内容我们来仿照一个网站&#xff08;戳我进网站&#xff09;的进入页面时的doing动画部分&#xff0c;首先是大标题从最小变为最大&#xff0c;然后是副标题从下向上走&#xff0c;最后是…

Proteus8.17下载安装教程

Proteus是一款嵌入式系统仿真开发软件&#xff0c;实现了从原理图设计、单片机编程、系统仿真到PCB设计&#xff0c;真正实现了从概念到产品的完整设计&#xff0c;其处理器模型支持8051、HC11、PIC10/12/16/18/24/30/DsPIC33、AVR、ARM、8086和MSP430等&#xff0c;能够帮助用…

工作-k8s问题处理篇

前言&#xff1a;公司这边为集团&#xff0c;所以项目较多&#xff0c;我目前总负责的项目架构有十六个&#xff0c;其中还有海外项目&#xff0c;不过底下也有一定的细分&#xff0c;同事解决不了的问题会升级到我这&#xff0c;只k8s容器平台常用的就有三种&#xff0c;一种是…

spring boot3.3.5 logback-spring.xml 配置

新建 resources/logback-spring.xml 控制台输出颜色有点花 可以自己更改 <?xml version"1.0" encoding"UTF-8"?> <!--关闭文件扫描 scanfalse --> <configuration debug"false" scan"false"><springProperty …

MySQL--SQL优化

目录 1 插入数据 1.1 insert优化 1.1.1 批量插入 1.1.2 手动提交事务 1.1.3 主键顺序插入 1.2 大批量插入数据 2 主键优化 2.1 数据组织方式 2.2 页分裂 2.3 页合并 2.4 主键设计原则 3 order by优化 4 group by优化 1. 使用索引 2. 减少数据集大小 3. 使用合适的聚…

【计算机网络】实验2:总线型以太网的特性

实验 2&#xff1a;总线型以太网的特性 一、 实验目的 加深对MAC地址&#xff0c;IP地址&#xff0c;ARP协议的理解。 了解总线型以太网的特性&#xff08;广播&#xff0c;竞争总线&#xff0c;冲突&#xff09;。 二、 实验环境 • Cisco Packet Tracer 模拟器 三、 实…

Java函数式编程【二】【Stream的装饰】【中间操作】【map映射器】【摊平映射器flatMap】

一、Java的Stream流式编程中的中间操作 Java的Stream流式编程中&#xff0c;中间操作是对数据流进行处理的一种方式&#xff0c;这些操作通常返回流对象本身&#xff0c;以便可以链接更多的操作。以下是一些常见的中间操作&#xff1a; filter(Predicate predicate) - 用于通过…